阅读更多

19顶
0踩

编程语言

原创新闻 ruby内存泄漏的罪魁祸首 - 幽灵指针

2008-12-05 13:01 by 见习编辑 robbin 评论(10) 有12370人浏览
ruby内存泄漏问题由来已久,几乎是一个无法克服的顽症。JavaEye对该问题有过探讨:Ruby VM的GC的思考。最近Ruby核心开发团队的邮件列表上面也对该问题进行了深刻的讨论,并且取得了一些相当不错的进展。

最早是有人报告了ruby的callcc调用引起的一个非常明显的内存泄漏现象:

while true
  @x = proc {|c| c}
end # 运行正常


while true
  x = callcc {|c| c}
end # 运行也正常


while true
  @x = callcc {|c| c}
end
# 严重泄漏内存!. 

while true
  g = Generator.new {|x| (1..3).each {|i| x.yield i}}
end # 严重泄漏内存


随后邮件列表围绕该问题进行了激烈的探讨:改进的C编码技巧解决Ruby内存泄漏

Brent Roman表示上述代码的内存泄漏根源在于GCC编译器对栈的分配的特点以及Ruby传统垃圾收集器的弱点造成的。

Brent Roman在memory leak in calcc这个帖子中指出:

gcc编译器不会自动初始化那些未被使用的、未初始化赋值的变量,而这些变量一旦被那些老的,未使用的,残留在内存栈中合法指针所引用以后,垃圾收集器GC就无法收集这些未被使用的变量了。

Brent Roman在ARM芯片的设备上面用Ruby 1.6.8开发机器人程序,在他的设备上内存只有32MB,但是ruby程序一天跑下来,就会吃掉超过20MB的内存。所以Brent花了很多时间给他的ruby 1.6.8打补丁。Brent介绍说,经过他自己的hack,目前他的ruby程序吃掉的内存已经稳定在10MB以下了。

Ruby内存泄漏的罪魁祸首原来在于“幽灵指针”!当应用程序的一个新的内存栈帧被推入到内存栈顶的时候,gcc编译的程序并不是让新的栈帧简单的覆盖先前的保存在该位置的栈帧,而且还会创建出来一些空闲的栈帧。而这些新的空闲栈帧有可能会被那些老的、残留在栈中的合法指针(即幽灵指针)所引用(例如空闲栈帧的地址刚好有一个老的指针指向该地址),这样一旦Ruby的传统GC垃圾收集器访问这些指针,这些指针指向的栈帧就被激活了,这就意味着这些空闲的栈帧再也无法被垃圾收集器回收,于是内存泄漏就诞生了!

此外ruby的eval方法调用的实现也有很大的问题,他会严重导致gcc创建出来大量的体积庞大的空闲栈帧。eval方法的每次调用会导致4KB的栈地址分配,这其中只有不到20%的栈空间会被真正初始化,这意味着:

1、幽灵指针有很高的可能性引用到超过80%的空闲栈帧,从而导致内存泄漏;
2、GC必须扫描一个包含了大量空闲栈帧的内存地址空间,把很多幽灵指针指向的永远不会被用到的对象标记为可用,而无法回收;
3、callcc方法调用(用来实现Continuations编程)和Ruby多线程应用程序的线程上下文切换会导致大量无用堆栈的拷贝操作
4、ruby递归调用很容易产生堆栈溢出

Brent Roman修改了eval实现以后,测试结果堆栈空间下降了超过2/3,同时线程上下文切换速度提高了3-4倍的速度。

由于Ruby on Rails框架大量使用了eval方法调用,产生内存泄漏的现象是非常明显的。Rails2.2已经开始支持多线程运行了,但是由于幽灵指针导致的内存泄漏问题,多线程切换会是一个严重的性能瓶颈,所以用Rails多线程,还是要三思而后行为好。

最后,Ruby的创始人松本行弘也发表了看法,鼓励Brent Roman早日将他的补丁移植到ruby 1.8.7版本和ruby 1.9版本上:

matz 写道
We are troubled by the "ghost references from the machine stack" generated by GCC for years.  We are more than happy to see the patch, and merge it if it's acceptable.


所以让我们耐心的期待一段时间吧。也许困扰我们的ruby内存泄漏问题,很快就将成为历史,不复存在!
19
0
评论 共 10 条 请登录后发表评论
10 楼 ray_linn 2011-07-07 10:16
Cruby基本是噩梦,VM太烂,还是JVM或者DLR比较靠谱
9 楼 moxie 2009-01-12 14:36
rbh 写道

求教Robbin——对于Rails用户来说,使用 JRuby 利用JVM是不是可以避免这个问题呢?

是的
8 楼 Magicloud 2008-12-23 10:41
看看ruby代码写的混乱程度……有缺陷不足为奇。
7 楼 janboo 2008-12-21 18:12
激动极了
激动极了
激动极了
激动极了
激动极了
6 楼 freedomstyle 2008-12-08 16:05
  呵呵  我对Ruby了解没有那么深,但看的出来,这个问题解决了,的确是一个很大的进步
5 楼 robbin 2008-12-06 22:20
rbh 写道

求教Robbin——对于Rails用户来说,使用 JRuby 利用JVM是不是可以避免这个问题呢?

当然可以,不过JRuby现在性能还是不足以应付高负载的web应用。
4 楼 fanix 2008-12-06 20:23
解决了这个问题,那就是个里程碑了
3 楼 t0uch 2008-12-06 11:02
期待这个patch,再加上圣诞的1.91 release,ruby可谓完善啊
2 楼 rbh 2008-12-05 21:06
求教Robbin——对于Rails用户来说,使用 JRuby 利用JVM是不是可以避免这个问题呢?
1 楼 xinghu 2008-12-05 18:36
天要亮了

发表评论

您还没有登录,请您登录后再发表评论

相关推荐

  • vfp6.0系统免费下载

    vf6.0,要考二级没系统的下哈 Microsoft Visual FoxPro 6.0 for Windows 的常见问题 这些是有关 Microsoft Visual FoxPro 最常见的问题。在您求助 Microsoft 产品支持服务之前,请先查阅这张列表。 若想打印这些附注,请从“文件”菜单中选择“打印”命令。此文档分为以下四部分: --------------------------------------------------------------------- 部分 1. 技术支持与市场 部分 2. Visual FoxPro 6.0 新增功能 部分 3. 从其他版本的 FoxPro 和 Visual FoxPro 中移植 部分 4. Visual FoxPro 常见问题 --------------------------------------------------------------------- 部分 1. 技术支持与市场 问题 1-1: 从何处可以获得产品的更新版本? 答案: 在 Visual FoxPro 的 Web 站点上即可获得产品的更新信息,其中包括有关 Service Pack 和更新的示例、向导及其他代码的信息,该站点的网址为: www.microsoft.com/vfoxpro 请定期查看该网站,以便下载产品的最新版本。 问题 1-2: 从何处可以得到有关 Visual FoxPro 的详细资料? 答案: 通过 Microsoft Visual FoxPro Web 站点是随时获得各种最新产品发布信息的最佳途径。在此站点上不仅有新的产品公告,而且还提供了产品的更新信息、技术文章、白皮书、专业开发人员设计的优秀示例、会议公告、以及与其他许多 FoxPro web 站点的各种链接。 问题 1-3: 如何获得技术支持,以及如何报告软件错误? 答案: Microsoft Visual FoxPro Web 站点已经链接到了多种联机支持选项,其中包括覆盖面广阔的有关所有产品 Microsoft Knowledge Base(Microsoft 知识库)。您还可以阅读一份有关常见问题的清单。除联机支持之外,还可以直接通过电话获得技术支持。“帮助”菜单中的选项可列出技术支持的电话号码。这些电话号码也可用于报告产品中的错误。 问题 1-4. 什么是 Knowledge Base?如何使用它? 答案: Knowledge Base 是内容广泛的论文集,覆盖了如何使用产品的各种特性、已知的软件错误及其解决方案或回避的方法、以及其他有助于使用各种 Microsoft 产品的有用信息。通过以下站点可访问整个 Knowledge Base: support.microsoft.com 问题 1-5: 是否会有 Visual FoxPro 6.0a? 答案: Microsoft 公司一向承诺为用户提供高质量的产品。如果确实需要,我们将提供 Visual FoxPro 6.0 的错误修订版。但是,修订版不会使用 6.0a 版的形式。Visual FoxPro 6.0 中任何错误的修正都将包含在 Visual Studio Service Pack 中。同时还会在 Visual FoxPro 的 www.microsoft.com/vfoxpro 或 Visual Studio 的www.microsoft.com/vstudio 的 Web 站点上发布修订公告。 问题 1-6: Microsoft 公司为应用程序的开发提供了一些优秀的解决方案。怎样才能知道应该向客户推荐和使用哪种产品? 答案: 在选择适用某项任务的产品时,需要考虑多方面的因素。Microsoft Visual FoxPro web 站点上有一份优秀的策略背景论文,它比较了 Visual FoxPro、Visual Basic、SQL Server 和 Access 等 Microsoft 产品之间的不同。 问题 1-7: 哪里可以找到 Visual FoxPro 的使用示例? 答案: Visual FoxPro 6.0 产品中带有丰富的示例,其中有一些是针对 6.0 版特有功能的新示例。与 Visual FoxPro 以前的版本不同,这些示例将与所有 Visual Studio 示例安装在一起。您必须运行 MSDN Library 的“自定义”安装来安装这些示例。在 Visual FoxPro 中可使用新的 HOME(2) 函数方便地找到已安装示例的位置。 除了产品中所自带的示例外,Microsoft Visual FoxPro web 站点还将经常提供新的示例。

  • 数据库操作系统——Visual FoxPro 6.0安装步骤

    数据库操作系统——Visual FoxPro 6.0安装步骤 Visual FoxPro数据库操作系统软件有很多版本,但最经典的是VF6.0版本,现在也有许多使用VF9.0,且大多数教材都是使用VF9.0作为实验平台。VF9.0安装大家可以自己下去尝试安装,它的使用和VF6.0差不多,只是部分功能增多了,但对于教学已足够了。下面我们主要介绍VF6.0的安装步骤: 视频教程链接:http://o...

  • vfp控制word光标位置_在Word中F1~F12功能键的作用,你都知道吗?

    Hi,大家好。Word是我们现在最常用的办公软件之一,靠着它,我们写文档、写论文、写方案…但是,你真的懂Word吗?其实,这个软件背后,还有一大批隐藏技能你不知道,掌握它们,你将开启新世界的大门。文档中常用的组合键一般是以【CTRL+字母】为主,其实键盘上的F1至F12都有它特殊的功能,可以帮助我们更好、更快捷的进行文档操作功能。今天老六就来为大家详细地讲解一下这些按键的功能和作用。F1 帮助在W...

  • 窗体透明,窗体上控件不透明的设置方法

    设置窗体的TransparencyKey 属性可以设置窗体全部透明,控件不透明,但这种只相当于opacity 100%的情况。 1.把窗体的背景色设成控件上没有的颜色(一定要和所有控件可能出现的颜色不一样哦,有一点一样的都会被透明掉)2.然后将窗体的TransparencyKey

  • VFP常用命令、函数、属性、事件和方法

    应用于ActiveDoc对象,复选框,列,组合框,命令按钮,命令组,容器对象,控件对象,临时表,自定义,数据环境,文件对象,编辑框,表单,表单集,表格,标头,图象,标签,线条,列表框,OLE绑定型控件,OLE容器控件,选项按钮,选项组,页面,页框,项目对象,ProjectHook对象,关系,_SCREEN,形状,微调,文本框,计时器,工具栏。应用于复选框,列,组合框,命令组,容器对象,控件对象,编辑框,表单,表格,标头,标签,选项按钮,选项组,页面,屏幕,形状,微调,文本框,工具栏。指定显示文本的字体名。

  • 文件函数对VFP数据库进行有效的加密

    每样事物都会有自己的薄弱环节,当然VFP也不例外。在VFP中有一个十分薄弱的环节就是数据库的保密性差。由于.DBF文件都是敞开式的,甚至用DOS中最简单的TYPE命令都可以浏览,因此,小编从以下两方面对数据进行加密...

  • VFP表单属性

    VFP表单属性如下: ActiveControl 0 引用一个对象上的活动控件 AlwaysOnTop .F.- 假(默认值) .T.- 真 防止其它窗口遮挡表单 AutoCenter .F.- 假(默认值) .T.- 真 指定表单对象第一次显示时是否自动位于VFP主窗口中央 BackColor 192,192,192 指定对象内文本和图形的背景色 BorderStyle 0-无边框 1-单线边

  • VFP6运行库、Visual FoxPro 6.0运行库

    Visual FoxPro 6.0运行库,解压将DLL文件释放到程序所在目录或者Windows的系统目录。

  • VFP编程技巧

    作者:未知 文章来源:黑妖蛇乐园BLOG 点击数:2297 更新时间:2005-12-30 在VFP中如何历遍所有文件夹和文件  在VFP中,能象一些杀毒软件那样,找遍磁盘的所有文件夹和文件吗?答案是肯定的,而且很简单:*利用VFP的Create Cursor -SQL命令建立有5个字段的临时库 *结合前面提到的ADIR()函数便可完成。下面是具体代码:

  • Vfp6的几个函数

    几个为Vfp6写的函数,单位系统用vfp6开发。不打算升级的Vfp9.针对现在互联网时代所写的几个函数   Func Strextract(cSearchExpression, cBeginDelim , cEndDelim , nOccurrence)  *!* *******************************************  *!* Create By Alan

  • VFP文件操作

    属性 功能 AvailableSpace 返回在指定的驱动器或网络共享上的用户可用的空间容量。 DriveLetter 返回某个指定本地驱动器或网络驱动器的字母,这个属性是只读的。 DriveType 返回指定驱动器的磁盘类型。 FileSystem 返回指定驱动器使用的文件系统类型。 FreeSpace 返回指定驱动器上或共享驱动器可用的磁盘空间,这个属性是只读的。 IsReady 确定指定的驱

  • VFP用replace更新表内容

    SELECT 1 &&选择工作区1 USE 父表 &&打开表1 SELECT 2 USE 子表 窗口——数据工作期——属性——修改——设子表中设代码为普通索引——索引顺序选择子表.索引**&&窗口操作 SET RELATION TO 父表.关键字 INTO B ADDITIVE SET SKIP TO 子表 &&在工作区1下,一对多表格状态下需要用 replace ALL B->需要更新字段 WITH A->参考字段 FOR

Global site tag (gtag.js) - Google Analytics