今天我在看 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

本文由 GCTT 原创编译,Go语言中文网 荣誉推出

Go 切片的一种有趣内存泄漏方式的更多相关文章

  1. web 开发之js---理解并解决IE的内存泄漏方式

    程序当中任何编程内存操作不当都会导致内存泄漏 http://wenku.baidu.com/link?url=8ba4UIn1aaevxTagH-F4vID79-bAfxdcLdeujGFn7PBnv ...

  2. Dictionary带来的一种隐式内存泄漏

    当心Dictionary带来的一种隐式内存泄漏 最近在看Dictionary的源代码的时候, 突然想到Dictionary的不当使用中有一种隐含内存泄漏的可能. 简化使用场景 小A正在写一个简单的图书 ...

  3. C的内存泄漏检测

    一,Windows平台下的内存泄漏检测 检测是否存在内存泄漏问题 Windows平台下面Visual Studio 调试器和 C 运行时 (CRT) 库为我们提供了检测和识别内存泄漏的有效方法,原理大 ...

  4. iOS开发 如何检查内存泄漏

    本文转载至 http://mobile.51cto.com/iphone-423391.htm 在开发的时候内存泄漏是不可避免的,但是也是我们需要尽量减少的,因为内存泄漏可能会很大程度的影响程序的稳定 ...

  5. hashCode竟然不是根据对象内存地址生成的?还对内存泄漏与偏向锁有影响?

    起因 起因是群里的一位童鞋突然问了这么问题: 如果重写 equals 不重写 hashcode 会有什么影响? 这个问题从上午10:45 开始陆续讨论,到下午15:39 接近尾声 (忽略这形同虚设的马 ...

  6. 为什么各大厂自研的内存泄漏检测框架都要参考 LeakCanary?因为它是真强啊!

    请点赞关注,你的支持对我意义重大. Hi,我是小彭.本文已收录到 GitHub · AndroidFamily 中.这里有 Android 进阶成长知识体系,有志同道合的朋友,关注公众号 [彭旭锐] ...

  7. JAVA内存泄漏解决办法

    JVM调优工具 Jconsole,jProfile,VisualVM Jconsole : jdk自带,功能简单,但是可以在系统有一定负荷的情况下使用.对垃圾回收算法有很详细的跟踪.详细说明参考这里 ...

  8. Java实现操作系统中四种动态内存分配算法:BF+NF+WF+FF

    1 概述 本文是利用Java实现操作系统中的四种动态内存分配方式 ,分别是: BF NF WF FF 分两部分,第一部分是介绍四种分配方式的概念以及例子,第二部分是代码实现以及讲解. 2 四种分配方式 ...

  9. glibc内存管理方式

    程序员接触的内存空间和系统接触的物理内存空间是有所区别的.对于一般进程来讲,他面对的是一个线性虚拟内存空间:地址从0到最大值.每一个进程面对的虚拟内存空间都是一样的,都享有全部的内存地址.虚拟内存空间 ...

随机推荐

  1. Arch Linux卡在 sddm 登录界面

    问题描述: 刚装完Arch Linux 之后发现能正常打开登录界面,但点击登录之后闪屏了一下又回到登录界面 可能的原因: /home 目录没挂载磁盘 user的权限没有设置好 解决办法: 对于第一种 ...

  2. Python basestring() 函数

    描述 basestring() 方法是 str 和 unicode 的超类(父类),也是抽象类,每组词 www.cgewang.com 因此不能被调用和实例化,但可以被用来判断一个对象是否为 str ...

  3. PHP vfprintf() 函数

    实例 把一些文本写入到名为 "test.txt" 的文本文件: <?php高佣联盟 www.cgewang.com$number = 9;$str = "Beiji ...

  4. ES与Javscript,JScript,ActionScript等脚本

    ES是一种语言标准,而后面的javascript.JScript.Actionscript都是基于ES的扩展语言. 实际上:javascript=ES+DOM+BOM 显然,JavaScript,JS ...

  5. C++关于智能指针

    有四种: auto_ptr<class T> unique_ptr<class T> shared_ptr<class T> weak_ptr<class T ...

  6. 【NOI2010】超级钢琴 题解(贪心+堆+ST表)

    题目链接 题目大意:求序列内长度在$[L,R]$范围内前$k$大子序列之和. ---------------------- 考略每个左端点$i$,合法的区间右端点在$[i+L,i+R]$内. 不妨暴力 ...

  7. 在Spring Boot中动态实现定时任务配置

    原文路径:https://zhuanlan.zhihu.com/p/79644891 在日常的项目开发中,往往会涉及到一些需要做到定时执行的代码,例如自动将超过24小时的未付款的单改为取消状态,自动将 ...

  8. 已解决:Invalid character found in the request target. The valid characters are defined in RFC 7230 and RFC 3986 问题

    请求: http://127.0.0.1:8080/driverApp/findLikeAddress?json={"shopname":"广东省"," ...

  9. 用python悄悄记录了室友的抖音在线时间

    今天给大家分享一篇有趣的文章,灵感来自于前几天与室友的聊天,他告诉我抖音可以实时显示人的在线情况,如下图: 很多人学习python,不知道从何学起.很多人学习python,掌握了基本语法过后,不知道在 ...

  10. Codechef May Challenge 2020 Division 1 记录

    目录 Triple Sort Sorting Vases Buying a New String Chef and Bitwise Product Binary Land Not a Real Wor ...