Go 切片的一种有趣内存泄漏方式
今天我在看 Prashant Varanasi 的 Go 发布会演讲:使用火焰图进行生产分析(Analyzing production using Flamegraphs),在演讲开始的第 28 分钟他提到了一种涉及切片的有趣且棘手的内存泄漏。为了自我提升,我将在这里写一下该内存泄漏的一种形式,并说明它是如何发生的。
首先,对于像 Go 这样的垃圾收集语言来说,内存泄漏是保留了对对象的非预期引用所造成的。垃圾收集器会帮你寻找并释放对象,但前提是它们事实上并没有被使用。如果你保留了对它们的引用,它们会留下来。 有时最终结果很简单(也行你故意保留一个较小的结构,但没意识到它引用了一个较大的结构),但有时候这种保留隐藏在某些东西的运行时实现里。这改变了我们对切片的看法。
简化之后,Prashant 处理的代码在一个切片中维护了当前在使用的元素的集合。当一个元素不再被使用时,它被转移到了切片的末尾,然后切片被截断而缩小(保持不变的是切片只保留使用的元素)。然而,缩小切片并不会缩小其依赖的数组,用 Go 的术语来说,减小了切片的长度但是并没有减少容量。由于底层依赖的数组没有变动,而该数组保留了一个理论上已经被丢弃了的元素的引用,以及该元素所引用的所有其他对象。即使是代码不可见的引用被保留,Go 垃圾收集器仍然会将该元素看做是还在使用中。代码认为以及被丢弃了的元素实际上并没有被释放,这就造成了内存泄漏。
现在,我查看了 Go 运行时和编译器代码,并对该问题进行了一些思考,我清楚地意识到了这是任何切片截断的通用问题。Go 绝不会尝试缩小切片的底层数组,而且通常来说这样做是不可能的,因为一个底层数组可能被多个切片或其他引用所共享。这显然会严重影响指向包含指针的对象的切片,但对于指向普通的旧数据的切片也可能很重要,尤其是当它们比较大的时候(比如你有一个 Point 的切片,每个 Point 有三个浮点数)。
对于包含指针或者包含持有着指针的结构的切片来说,明显的修复方式(这是Uber 代码中采用的修复方式)是在截断切片之前将末尾的指针置为空。这样保留了完整的底层数组,但抛弃了对其他内存的引用,而这些其他的内存是真正内存泄漏的地方。
对于实际的底层数组可能会有大量内存消耗的切片来说,我想到可能有两种做法,一种特殊,一种通用。特殊的一种是检查代码中“大小截断为零”的情况,并专门将切片本身置为空,而不是仅仅使用标准的切片截断功能来截断。通用的做法是明确地强制使用切片拷贝而不是仅仅截断(就如我对切片可变性的评论提到的)。强制使用拷贝所带来的缺点是,某些时候可能会带来更大的开销。你可以通过仅在切片的容量远远超出新切片的长度的时候才强制使用拷贝的方式来进行优化。
补充:(对垃圾收集而言)三索引的切片截断是危险的
Go 切片表达式允许在起终点之外,使用很少使用的第三个索引来设置新切片的容量。你也许会想到采用这种形式限制切片,来作为解决垃圾收集问题的办法:
slc = slc[:newlen:newlen]
不幸的是,这样并不会达到你想要的效果,而且会适得其反。设置新切片的容量完全不会改变底层的依赖数组,也不会让 Go 分配一个新的内存,但这却意味着你无法获取数组大小的信息(否则可以通过切片的容量来得到它)。这样造成的唯一影响是强制随后的 append() 重新分配新的底层数组。
via: https://utcc.utoronto.ca/~cks/space/blog/programming/GoSlicesMemoryLeak
作者:ChrisSiebenmann 译者:dust347 校对:polaris1119
Go 切片的一种有趣内存泄漏方式的更多相关文章
- web 开发之js---理解并解决IE的内存泄漏方式
程序当中任何编程内存操作不当都会导致内存泄漏 http://wenku.baidu.com/link?url=8ba4UIn1aaevxTagH-F4vID79-bAfxdcLdeujGFn7PBnv ...
- Dictionary带来的一种隐式内存泄漏
当心Dictionary带来的一种隐式内存泄漏 最近在看Dictionary的源代码的时候, 突然想到Dictionary的不当使用中有一种隐含内存泄漏的可能. 简化使用场景 小A正在写一个简单的图书 ...
- C的内存泄漏检测
一,Windows平台下的内存泄漏检测 检测是否存在内存泄漏问题 Windows平台下面Visual Studio 调试器和 C 运行时 (CRT) 库为我们提供了检测和识别内存泄漏的有效方法,原理大 ...
- iOS开发 如何检查内存泄漏
本文转载至 http://mobile.51cto.com/iphone-423391.htm 在开发的时候内存泄漏是不可避免的,但是也是我们需要尽量减少的,因为内存泄漏可能会很大程度的影响程序的稳定 ...
- hashCode竟然不是根据对象内存地址生成的?还对内存泄漏与偏向锁有影响?
起因 起因是群里的一位童鞋突然问了这么问题: 如果重写 equals 不重写 hashcode 会有什么影响? 这个问题从上午10:45 开始陆续讨论,到下午15:39 接近尾声 (忽略这形同虚设的马 ...
- 为什么各大厂自研的内存泄漏检测框架都要参考 LeakCanary?因为它是真强啊!
请点赞关注,你的支持对我意义重大. Hi,我是小彭.本文已收录到 GitHub · AndroidFamily 中.这里有 Android 进阶成长知识体系,有志同道合的朋友,关注公众号 [彭旭锐] ...
- JAVA内存泄漏解决办法
JVM调优工具 Jconsole,jProfile,VisualVM Jconsole : jdk自带,功能简单,但是可以在系统有一定负荷的情况下使用.对垃圾回收算法有很详细的跟踪.详细说明参考这里 ...
- Java实现操作系统中四种动态内存分配算法:BF+NF+WF+FF
1 概述 本文是利用Java实现操作系统中的四种动态内存分配方式 ,分别是: BF NF WF FF 分两部分,第一部分是介绍四种分配方式的概念以及例子,第二部分是代码实现以及讲解. 2 四种分配方式 ...
- glibc内存管理方式
程序员接触的内存空间和系统接触的物理内存空间是有所区别的.对于一般进程来讲,他面对的是一个线性虚拟内存空间:地址从0到最大值.每一个进程面对的虚拟内存空间都是一样的,都享有全部的内存地址.虚拟内存空间 ...
随机推荐
- [leetcode/lintcode 题解] 谷歌面试题:找出有向图中的弱连通分量
请找出有向图中弱连通分量.图中的每个节点包含 1 个标签和1 个相邻节点列表.(有向图的弱连通分量是任意两点均有有向边相连的极大子图) 将连通分量内的元素升序排列. 在线评测地址:https://ww ...
- sed 指定行范围匹配
sed -n '5,10{/pattern/p}' file sed是一个非交互性性文本编辑器,它编辑文件或标准输入 导出的文件拷贝.标准输入可能是来自键盘.文件重定向.字符串或变量,或者是一个管道文 ...
- Fortify Audit Workbench 笔记 Unreleased Resource: Database( 未释放资源:数据库)
Unreleased Resource: Database 未释放资源:数据库 Abstract 程序可能无法成功释放某一项系统资源. Explanation 程序可能无法成功释放某一项系统资源. 资 ...
- mongoose.model第三个参数的问题
这个是个好问题,之前按照教程做的数据库没有问题,现在自己从新做出现了问题.还好之前有无意中接触了这个知识点,不然感觉真的很难解决. 在检查完所有东西都没错的时候(前端传给req的数据正常,与数据库相符 ...
- 将BX中的数以二进制形式在屏幕上显示出来。
问题 将BX中的数以二进制形式在屏幕上显示出来. 代码 code segment assume cs:code main proc far start: mov bx,011001100110b ;假 ...
- PHP is_writable() 函数
定义和用法 is_writable() 函数检查指定的文件是否可写. 如果文件可写,该函数返回 TRUE. 语法 is_writable(file) 参数 描述 file 必需.规定要检查的文件. 提 ...
- P5979 [PA2014]Druzyny dp 分治 线段树 分类讨论 启发式合并
LINK:Druzyny 这题研究了一下午 终于搞懂了. \(n^2\)的dp很容易得到. 考虑优化.又有大于的限制又有小于的限制这个非常难处理. 不过可以得到在限制人数上界的情况下能转移到的最远端点 ...
- [转]Java CPU 100% 排查技巧
文章来源:微信公众号:猿天地 平时多积累一点,这样在遇到问题的时候就少句求人的话.如果在实际的开发中遇到CPU 100%问题,要怎么排查呢?如果你没有遇到过这个问题,请先自己思考10s,如果你遇到过, ...
- MyBatis-Plus使用(4)-集成SpringBoot
我这里使用的MyBatis-Plus是当前最新的3.2.0版本, 1. 引入需要的jar,基础jar包括: <dependencies> <dependency> <gr ...
- 40行Python制作超炫酷动态排序图,有了它高逼格PPT再也不愁!
本文首发于量化投资与机器学习 转载于 https://mp.weixin.qq.com/s/KaB_7oXZf0_IV97y0pRPmQ 前言 最近,这种动态排序条形图视频超级火,如下图: ...