垃圾回收(GC)的三种基本方式

垃圾(Garbage)就是程序需要回收的对象,如果一个对象不在被直接或间接地引用,那么这个对象就成为了「垃圾」,它占用的内存需要及时地释放,否则就会引起「内存泄露」。有些语言需要程序员来手动释放内存(回收垃圾),有些语言有垃圾回收机制(GC)。本文就来讨论GC实现的三种基本方式。

其实这三种方式也可以大体归为两类:跟踪回收,引用计数。美国IBM的沃森研究中心David F.Bacon等人发布的「垃圾回收统一理论」一文阐述了一个理论:任何垃圾回收的思路,无非以上两种的组合,其中一种的改善和进步,必然伴随着另一种的改善和进步。

跟踪回收

跟踪回收的方式独立于程序,定期运行来检查垃圾,需要较长时间的中断。

标记清除

标记清除的方式需要对程序的对象进行两次扫描,第一次从根(Root)开始扫描,被根引用了的对象标记为不是垃圾,不是垃圾的对象引用的对象同样标记为不是垃圾,以此递归。所有不是垃圾的对象的引用都扫描完了之后。就进行第二次扫描,第一次扫描中没有得到标记的对象就是垃圾了,对此进行回收。

复制收集

复制收集的方式只需要对对象进行一次扫描。准备一个「新的空间」,从根开始,对对象进行扫,如果存在对这个对象的引用,就把它复制到「新空间中」。一次扫描结束之后,所有存在于「新空间」的对象就是所有的非垃圾对象。

这两种方式各有千秋,标记清除的方式节省内存但是两次扫描需要更多的时间,对于垃圾比例较小的情况占优势。复制收集更快速但是需要额外开辟一块用来复制的内存,对垃圾比例较大的情况占优势。特别的,复制收集有「局部性」的优点。

在复制收集的过程中,会按照对象被引用的顺序将对象复制到新空间中。于是,关系较近的对象被放在距离较近的内存空间的可能性会提高,这叫做局部性。局部性高的情况下,内存缓存会更有效地运作,程序的性能会提高。

对于标记清除,有一种标记-压缩算法的衍生算法:

对于压缩阶段,它的工作就是移动所有的可达对象到堆内存的同一个区域中,使他们紧凑的排列在一起,从而将所有非可达对象释放出来的空闲内存都集中在一起,通过这样的方式来达到减少内存碎片的目的。

引用计数

引用计数是指,针对每一个对象,保存一个对该对象的引用计数,该对象的引用增加,则相应的引用计数增加。如果对象的引用计数为零,则回收该对象。

优点:引用计数最大的优点就是容易实现,C++程序员应该都实现过类似的机制。二是成本小,基本上引用计数为0的时候垃圾会被立即回收,而其他方法难以预测对象的生命周期,垃圾存在的时间都会比这个方法高。另,这种垃圾回收方式产生的中断时间最短。

缺点:最著名的缺点就是如果对象中存在循环引用,就无法被回收。例如,下面三个对象互相引用,但是不存在从根(Root)指向的引用,所以已经是垃圾了。但是引用计数不为0.

DC_counter_way

还有一个缺点就是,引用计数不适合在并行中使用,多个线程同时操作引用计数,会引起数值不一样的问题从而导致内存错误。所以引用计数必须采用独占方式,如果引用操作频繁,那么加锁等并发控制机制的开销是相当大的。

Perl和Python采用了这种GC机制。

它们的衍生算法

分代回收

这种回收方式用了程序的一种特性:大部分对象会从产生开始在很短的时间内变成垃圾,而存在的很长时间的对象往往都有较长的生命周期。高频对新生成的对象进行回收,称为「小回收」,低频对所有对象回收,称为「大回收」。每一次「小回收」过后,就把存活下来的对象归为「老生代」,「小回收」的时候,遇到老生代直接跳过。大多数分代回收算法都采用的「复制收集」方法,因为小回收中垃圾的比例较大。

这种方式存在一个问题:如果在某个新生代的对象中,存在「老生代」的对象对它的引用,它就不是垃圾了,那么怎么制止「小回收」对其回收呢?这里用到了一中叫做写屏障的方式。

程序对所有涉及修改对象内容的地方进行保护,被称为「写屏障」(Write Barrier)。写屏障不仅用于分代回收,也用于其他GC算法中。

在此算法的表现是,用一个记录集来记录从新生代到老生代的引用。如果有两个对象A和B,当对A的对象内容进行修改并加入B的引用时,如果①A是「老生代」②B是「新生代」。则将这个引用加入到记录集中。「小回收」的时候,因为记录集中有对B的引用,所以B不再是垃圾。

增量回收

上面的算法缩短了「GC平均中断时间」,但是在对实时性要求很高的程序中,对「GC最高中断时间」的要求更高。比如,自动驾驶软件,如果某次GC中断了0.1s,那么损失可能是致命的。

增量回收就是将GC分成几部分来执行。设置「GC最多中断10ms」这样的条件限制来使GC的终端时间视作可预测的。

但是,在两段的GC程序之间,引用关系可能发生了变化。所以,这种GC算法也要写屏障,来记录引用关系的变化。虽然这种方式控制了中断最高时间,但是由于中断次数增加,GC总时间是增加的。

并行回收

基本原理是,在程序运行的同时进行GC工作,最大化CPU的性能。但是这种方式也要面对增量回收的问题,所以也要进行写屏障操作。

然而这种方式也并未做到完全不暂停原程序的运行,在某些特定的GC阶段还是要暂停原程序。多核化迅速发展的今天,这种算法也在不断优化。不间断原程序实现并行回收这个领域是相当值得期待的。

 

在编程中体验纯粹的快乐

Learn Python The Hard Way 的最后,有一个「老程序员的建议」,来告诫学完了这个教程的同学们不要拘泥于编程语言,不要陷入「关于语言的迷信和争吵」中,无论是否从事的是计算机行业,都可以爱上编程,从中的到乐趣。这个老程序员的忠言翻译如下:

现在你已经完成了这个教程,并决定继续深入学习。编程可能成为你的事业,也可能成为你的一个爱好。所以你可能需要一些建议,来保证少走弯路,并从这个「新欢」中的到最大的乐趣。

我从事编程已经很长时间了,长到对我来说这已经是一件极其无聊的工作。我在写这本书的时候,已经懂20门编程语言,能在一天到一个周的时间学会一项新语言(取决于它有多么古怪)。即使这样,我还是对此感到无聊,不再有任何兴趣。但这并不是说编程是很无聊的,也不是说你在将来会觉得它无聊,我意思是,我在干到现在这个年纪,觉得没意思了。

经过这么多年,我发现一个真理:用哪一个编程语言并不重要,重要的是用它来做什么。其实这道理我早就懂,不过还是经常忽视,还是会被编程语言分心。但从现在开始我不会再忘了,你最好也记住。

你学哪门语言,用哪门也都不重要,千万不要陷入对语言的宗教崇拜中,那只会让你忘记原来的目的:把编程语言当做一个工具来做有趣的事情。

编程作为一种智力活动,几乎是唯一一种能创造交互艺术的艺术形式了。你可以写软件让别人来玩,甚至可以通过这种形式直接和别人对话。别的艺术都没有这种交互性。电影拍出来之后直接播放给观众,图画不会动,但是代码能做到。

从事编程行业所获得的乐趣其实一般。这份工作确实不错,但是你可以经营一个快餐店来赚一样多的钱,还更轻松快乐。所以你最好在别的领域将编程作为一个秘密武器。

在科技公司工作的人会编程并没有什么特殊的,也不会获得特殊的尊重。但是从事生物、化学、政治、公务员、社会学、物理、历史和数学的人如果会编程就会格外受到尊重,因为他们能做到这些了不起的事情,来发展他们的学科。

当然了,这些建议都没什么意义。如果你真的喜欢编程,你尝试通过任何方式用它来提高你的生活。尽情去探索这个怪异、神奇、充满智慧的,50年来人们都一直孜孜不倦在探索的世界吧!愿快乐永远与你同在。

最后不得不提的一点,学着写软件可能让你变得有些与众不同。不管是好是坏,总之是不同了。可能有人会对你刻薄,比如在你身上用「书呆子」(nerd)这个词;可能你会发现因为你强大的逻辑,别人都不愿意和你争吵;可能你甚至会发现你懂计算机的运作原理,别人因为觉得你怪异、不合群。

对这些情况我只有一条建议:让他们去死吧!(They can go to hell.)这个世界需要古怪的人,需要书呆子,他们清楚或者热衷于弄清楚事情运作的原理。当真的有人如此对你的时候,要记住:这是你自己的路,不是他们的。与众不同不是犯罪,别人这么说你只是因为他们嫉妒,他们永远不敢在自己的白日梦里奢求这些。

You can code. They cannot. That is pretty damn cool.

 

从《美丽新世界》谈自由

不得不承认,我认为对于人类社会文明的发展来说,《美丽新世界》中描绘的社会的确是一个完美的社会。每一个人都是整体的一部分,极其稳定,人类幸福度高,无忧无虑,安居乐业。但这也是一个及其恐怖的社会。

cover new

在这个完美世界中,「分娩」被认为是淫秽的事情。人类靠试管中的婴儿繁衍后代,「家庭」同样被视为是肮脏的概念,社会中的个人不存在和某个人有特殊的感情。每个男人属于所有的女人,每个女人属于所有的男人。所有的人都可以按照喜好每天选择不同的人性交。每个人都在大剂量的服用性激素和神经类药品(唆麻),一有任何不在「正常范围之内」的小事情就靠药品来逃避。

3fd214221b37441a70a2da45a1a6e041.619x375x1

婴儿还小的时候,育婴室就循环播放录音,达到「洗脑」的效果。例如「母亲是肮脏的」,「历史是废话」,「和家人一起生活将会非常恐怖」等等。书中还提到另一种潜意识的训练——让幼儿去接触鲜花和书籍,然后再给他们电击,以保证他们长大以后不会再碰这些东西。

brave new 1

为了社会稳定,每一个人的个性,感情都被磨灭。个人只是社会的螺丝钉,而社会的等级制度非常森严。从α到ε,分成不同的等级。人们从小的时候就被灌输这种等级制度,在试管里时加入不同的血清使不同等级的人长相区别明显,童年时期穿不同的衣服,玩不同的玩具。这样成年时会有根深蒂固的等级概念。α会觉得自己的工作高雅,看不起ε的体力活。ε会认为自己的工作简单轻松,不像α需要体力劳动。

brave_new_world_social_classes_by_qbark-d4ujz5s

 

这种稳定的社会最怕的就是「个性」。书中说:「文明是绝对不需要高贵行为和英雄主义的。这些事情是政治无能的症状。只有在有战争的时候,英雄主义才会有一点意义。但是现在没有战争,最大的问题就是防止你爱一个人爱的太深。

这个世界看似完美,实际也是。如果这是「文明五」中的一个世界,那么衡量这个社会的所有标准:人口(通过人工繁殖严格控制),经济,科技,幸福度都是无敌的,除了一点——文化。这个社会中人们的娱乐都是「感官刺激」,靠的是唆麻、感观电影。书籍和宗教会让人产生独立于社会体制的思考,所以遭到了根除。但是仔细一想,这样的社会竟然可以正常运作,难道文化在社会中真的没有作用?

不是的。我认为这样的社会完全偏离了方向。社会的终极目标应该是三个哲学问题,如果有重点,那么可能我们最后造出《银河系漫游指南》中的超级计算机来得出答案,可能文化高度发达有人提出并论证了这个答案,可能接触到外星文明,亦或者别的形式的答案。社会总要向着民主,平等的方向发展。文化,是我们存在过的证据,自由和思考,是存在的意义和形式。美丽新世界虽然完美,但这个人们却活的毫无意义。所以书中野蛮人有这样的呐喊:

“可我不想要舒适。我想要上帝,我想要诗歌,我想要真实的危险,我想要自由,我想要善良,我想要罪恶。”

有选择才算是自由,自出生开始被人安排了一切,这和「奴隶制」一样野蛮。世界上不存在不劳而获的幸福,幸福就意味着代价。美丽新世界的幸福,是以牺牲真相为代价的。我宁愿不要这种廉价的幸福,得知真相,痛苦,思考,反省,吸取教训。社会中的每个人都有权利知道真相。这才是自由。

我们现在的科技和网络如此发达,好像我们可以轻易地做自己想做的事情。实则是「美丽新世界」的这种自由。天津爆炸事件之后,大家的焦点仅集中在上面两三天,接着就被娱乐、八卦转移了注意力。相比于独裁政治,这种控制更加可怖。尼尔·波兹曼在《娱乐至死》中一语中的的表达了《美丽新世界》相比于《1984》更加危险:

       在《1984》中,人们受制于痛苦,而在《美丽新世界》中,人们由于享乐失去了自由。奥威尔担心我们憎恨的东西会毁掉我们,而赫胥黎担心的是,我们将毁于我们热爱的东西。

附《娱乐至死》漫画节选p25092201

p25092384

p25092404

p25092448

p25092469

 

p25092483

p25092546

p25092553

 

在快钱实习

下午做完了最后的工作——写文档和注释——在快钱的两个月实习就算是全部结束了。其实这项工作可以从六月算起,那时候虽然还没到公司,但现在看起来,日常基本上和在公司工作的时候是一样的。得到这份实习是因为这个学期的操作系统课(我从小学开始就有特别容易和老师混熟的特异功能),李老师介绍了这份实习。其实一开始,我是拒绝的。因为觉得自己对研发(相对于“开发”来说)性的工作不感兴趣,但是暑假又没有别的计划,于是就去面试了。面试的时候吕博给我介绍了工作内容,欣然接受。于是六月就一边应付考试一边准备工作用到的知识,7月2号考试一结束就去上班了。

工作的内容是“文本挖掘”,需要用到自然语言处理(NLP)和爬虫的知识。说的再简单一些,就是公司有一些消费数据,通过这些数据挖掘到更多的信息,给这些数据加上一些能反映用户的消费倾向的信息,进而可以制作用户画像,再进一步就可以做“个性推荐”啦。

这份实习让我学到了不少东西,从一开始没有接触过NLP和Python,现在已经能写出爬虫程序,并且分析文本了。不得不提,我觉得其中最难的是中文编码和中文分词(哭),大多数语言(例如英语,法语,德语)等都是有空格来分词的,但是中日韩文这些亚洲语言,用起来就想这篇文章一样,只有句子之间有间隔,词与词之间是没有间隔的,要多做一份工作。至于中文编码嘛……谁写谁知道,说多都是泪。但是其实最后的成果比我预期的要差,主要是因为我们手里得数据质量太差了,信息有限,只能依靠爬虫去网络上抓取更多信息,但是本来就差的数据,抓回来的也不太高。

对了,上班第一天开的一个会让我现在都记忆犹新,不得不提一下。是一个百分点介绍他们的业务的会议。这是一个专业做大数据的公司,靠在他们的客户网站上挂代码,获得用户行为,在应用到个性推荐上。比如说,你在网站A上浏览了冰箱,那么你下次上B网站,他们就在首页给你推荐冰箱。不仅限于购物网站,新闻网站,门户网站等一切需要流量的网站都有用武之地。这个会议让我对大数据的应用叹为观止,以前就是听说过这么个概念,现在才真正接触到(讽刺的是,人类的一切最新的科技都会首先用在军事和消费上,呵呵)。说起来,我跟朋友们谈这个,他们普遍的反映都是很反感“个性推荐”,觉得这侵犯他们的“隐私”了。我对这个感觉还好,我觉得一个人只要是上网就不存在隐私了,网络上基本所有的数据都是公开的。

公司在浦东浦电路,每天要坐3个半小时地铁来回啊!写代码不累,坐地铁可累死了,而且上下班的时候正是高峰,人特别挤!实习期间经历了公司被万达收购,从陆家嘴投资大厦搬到世纪金融广场,可是距离只变的更远了(哭),给我的经验就是:以后上班宁愿贵一点也一定要住在公司附近,不然太浪费时间了。

20150824_180125

说起来我还是蛮认真的嘿嘿,基本上每天来的都很早很早。

20150810_081854

新公司某办公室发现了这件旗子——别拦着我!为了部落!

20150814_102939

离开学还有十多天,我的假期真正的开始了!我要在这段时间里完成之前写了一半但是没写下去的小玩具,请大家期待吧!这篇文章不谈技术,但是最近我会在博客上写写实习的时候遇到的好玩的东西~

 

 

迷人的嗓音和迷人的故事——《Sleepyhead》

今天更新了博客的主题,用了三栏布局,相比一栏,我觉得同样可以让读者集中精力,而且缩短了行长,在屏幕上阅读起来更加方便。使用柔和的色调,和舒服的顶部图片,希望大家能喜欢。如果有建议可以给我留言~

第一篇就衬托一下这个主题,给大家讲一个故事,和一首歌吧。这是一首Galen Crew的《Sleepyhead》。Galen从小就痴迷音乐,在爱上吉他之前,尝试过单簧管、钢琴和架子鼓,随着吉他越来越厉害,创作激情也越来越高涨,后来发现自己了自己与众不同的嗓音,和其余两人组成了一个独特的声音组合。

这首歌就不用多介绍了,下面是我翻的歌词大意,看了就懂,enjoy~

沉睡的公主

in the year of our lord 1239
公元纪年1239年
there once lived a girl of the royal line
曾经有一位有王室血统的女孩
the ancient stories do recall ?
古老的故事中说
she was the fairest of them all
她是世界上最美的女孩
in the castle made of stone
在一个石头城堡里
every night she slept alone
她每夜独自入睡

any noice that would raise the dead
连死人都可以吵醒的声音
couldn’t wake her sleepyhead
都无法唤醒她
the stranger came from the foreign land
从一个遥远的国度来了一位陌生人
asking for the maiden’s hand
希望能牵起女孩的手
her father said no go away
她的父亲说,不行,走开
she’s gonna marry a king one day
她以后要嫁给一个国王
the stranger he came back again
陌生人走了,后来又回来了
riding with 10 thousand men
带着一万骑士
the battle cries few always dread ?
战斗的呼喊,没有人不怕
but couldn’t wake her sleepyhead
但还是无法唤醒她
the fighting lasted all day long
战斗持续了一整天
but the castle wall‘s very thick and strong
但城堡的墙壁又厚又强
the stranger cried let her decide
陌生人哭喊,让她决定吧
where her true affections lie
让她决定选择谁
so the king knocked on her door
于是国王敲响了她的门
only you can end this war
“只有你能结束这场战争”
no one knows how the story ends
没人知道这个故事的结局
did she ever wake up again?
她醒来了么?
will she ever wake up again?
她还会醒来么?