首页
|
新闻
|
新品
|
文库
|
方案
|
视频
|
下载
|
商城
|
开发板
|
数据中心
|
座谈新版
|
培训
|
工具
|
博客
|
论坛
|
百科
|
GEC
|
活动
|
主题月
|
电子展
注册
登录
论坛
博客
搜索
帮助
导航
默认风格
uchome
discuz6
GreenM
»
MCU 单片机技术
» 对比Ruby和Python的垃圾回收(2)
返回列表
回复
发帖
发新话题
发布投票
发布悬赏
发布辩论
发布活动
发布视频
发布商品
对比Ruby和Python的垃圾回收(2)
发短消息
加为好友
我是MT
当前离线
UID
1023166
帖子
6651
精华
0
积分
3328
阅读权限
90
来自
燕山大学
在线时间
230 小时
注册时间
2013-12-19
最后登录
2016-1-5
论坛元老
UID
1023166
性别
男
来自
燕山大学
1
#
打印
字体大小:
t
T
我是MT
发表于 2015-2-7 11:01
|
只看该作者
对比Ruby和Python的垃圾回收(2)
垃圾回收
回到Ruby,由于我们分配越来越多的对象,Ruby将继续为我们从空闲对象链表(free list)获取预分配对象。因此,空闲对象链表将变得越来越短:
或者更短:
请注意,我将一个新的值赋给了n1,Ruby会遗留下旧的值。”ABC”, “JKL”和”MNO”等结点对象会依然保留在内存中。Ruby不会立即清理旧的对象尽管程序不再使用!作为一名Ruby开发者就像生活在一个脏乱的房间,衣服随意的仍在地板上,厨房的水槽中堆满了脏盘子。作为一个Ruby开发者,你必须在一大堆垃圾对象中去工作。
当你的程序不在使用任何对象的时候,Python会立刻进行清理。
Python开发者生活在一所整洁的房子
垃圾回收机制在Python和Ruby中迥然不同,让我们回到前面三个Python中Node对象的例子:
内部的,每当我们新建一个对象,Python将在对象对应的C语言结构中保存一个数字,叫做引用技术。最初,Python将它的值设为1。
值为1表明每个对象有一个指针或引用指向它。假设我们创建一个新的对象,JKL:
正如前面所说,Python将”JKL”的引用计数设置为1。同样注意到我们改变n1指向了”JKL”,不再引用”ABC”,同时将”ABC”的引用计数减少为0。
通过这一点,Python垃圾回收器将会立即执行!无论何时,只要一个对象的引用计数变为0,python将立即释放这个对象,并且将它的内存返回给操作系统。
上图中,Python将回收”ABC”对象的内存。记住,Ruby只是将旧的对象遗留在那里并且不去释放它们占用的内存。
这种垃圾回收算法被称为”引用计数”,由乔治柯林斯发明于1960年。非常巧合的是在同一年约翰麦卡锡大叔发明了”空闲对象链表算法”。正如Mike Bernstein在Ruby Conference大会上所说”1960年是属于垃圾回收器的…”。
作为一个Python开发者,就像生活在一个整洁的房间中。你知道,你的室友有些洁癖,他会把你使用过的任何东西都清洗一遍。你把脏盘子,脏杯子一放到水槽中他就会清洗。
现在看另外一个例子,假设我们让n2和n1指向同样的结点:
上图左边可以看到,Python减少了”DEF”的引用计数并且立即回收了”DEF”对象。同时可以看到,由于n1和n2同时指了”JKL”对象,所以它的引用计数变为了2。
标记回收算法
最终脏乱的房间将堆慢垃圾,生活不能总是如此。Ruby程序在运行一段时间之后,空闲对象链表最终将被用尽。
上图中所有的预分配对象都被用尽(方块全部变成了灰色),链表上没有对象可用(没有剩余的白色方块)。
此时,Ruby使用了一种由约翰麦卡锡发明的被称为”标记回收”的算法。首先,Ruby将停止程序的执行,Ruby使用了”停止这个世界,然后回收垃圾”的方式。然后,Ruby会扫描所有的指向对象和值的指针或引用。同样,Ruby也会迭代虚拟机内部使用的指针。它会标记每一个指针所能到达的对象。在下图中,我使用了”M”指出了这些标记:
上面三个”M”标记的对象为活跃对象,依然被我们的程序使用。在Ruby解释器内部,通常使用”free bitmap”的数据结构来保存一个对象是否被标记:
Ruby将”free bitmap”保存在一个独立的内存区域,以便可以更好的利用Unix的”copy-on-write”特性。更详细的信息,请参考我的另一篇文章《为什么Ruby2.0的垃圾回收器让我们如此兴奋》。
如果活跃对象被标记了,那么其余的便是垃圾对象,意味着它们不再会被代码使用。在下图中,我使用白色的方块表示垃圾对象:
接下来,Ruby将清理没有使用的,垃圾对象,将它们链入空闲对象链表(free list):
在解释器内部,这个过程非常迅速,Ruby并不会真正的将对象从一个地方拷贝到另一个地方。相反的,Ruby会将垃圾对象组成一个新的链表,并且链入空闲对象链表(free list)。
现在,当我们要创建一个新的Ruby对象的时候,Ruby将为我们返回收集的垃圾对象。在Ruby中,对象是可以重生的,享受着多次的生命!
标记回收算法 vs. 引用计数算法
咋一看,Python的垃圾回收算法对于Ruby来说是相当让人感到惊讶的:既然可以生活在一个整洁干净的房间,为什么要生活在一个脏乱的房间呢?为什么Ruby周期性的强制停止程序的运行去清理垃圾,而不使用Python的算法呢?
然而,引用计数实现起来不会像它看起来那样简单。这里有一些许多语言不愿像Python一样使用引用计数算法的原因:
首先,实现起来很困难。Python必须为每一个对象留有一定的空间来保存引用计数。这会导致一些细微的内存开销。但更遭的是,一个简答的操作例如改变一个变量或引用将导致复杂的操作,由于Python需要增加一个对象的计数,减少另一个对象的计数,有可能释放一个对象。
其次,它会减慢速度。尽管Python在程序运行过程中垃圾回收的过程非常顺畅(当你把脏盘子放到水槽后,它立马清洗干净),但是运行的并不十分迅速。Python总是在更新引用计数。并且当你停止使用一个巨大的数据结构时,例如一个包含了大量元素的序列,Python必须一次释放许多对象。减少引用计数可能是一个复杂的,递归的过程。
最后,它并不总是工作的很好。在我演讲的下一部分,也就是下一篇帖子中能看到,引用计数不能处理循环引用数据结构,它包含循环引用。
下一次…
下周我将发布演讲的其他部分。我将讨论Python怎样处理循环引用数据结构,以及在即将到来的Ruby2.1中,垃圾回收器是怎样工作的。
收藏
分享
评分
回复
引用
订阅
TOP
返回列表
电商论坛
Pine A64
资料下载
方案分享
FAQ
行业应用
消费电子
便携式设备
医疗电子
汽车电子
工业控制
热门技术
智能可穿戴
3D打印
智能家居
综合设计
示波器技术
存储器
电子制造
计算机和外设
软件开发
分立器件
传感器技术
无源元件
资料共享
PCB综合技术
综合技术交流
EDA
MCU 单片机技术
ST MCU
Freescale MCU
NXP MCU
新唐 MCU
MIPS
X86
ARM
PowerPC
DSP技术
嵌入式技术
FPGA/CPLD可编程逻辑
模拟电路
数字电路
富士通半导体FRAM 铁电存储器“免费样片”使用心得
电源与功率管理
LED技术
测试测量
通信技术
3G
无线技术
微波在线
综合交流区
职场驿站
活动专区
在线座谈交流区
紧缺人才培训课程交流区
意见和建议