《垃圾回收的算法与实现》作者中村成洋&相川光:高手对话,揭秘GC

635 查看

本文仅用于学习和交流,不用于商业目的。非商业转载请注明作译者、出处,并保留本文的原始链接:http://www.ituring.com.cn/art...

访谈对象:

中村成洋
Network Applied Communication Laboratory Ltd. 研究员。因为偶然的机会对GC产生浓厚兴趣,其本人却说不清楚为何喜欢GC,当被人追问原因时,总是回答“是缘分”。现在是CRuby的commiter,每天致力于GC的改善。如你所猜,跟Ruby之父——松本行弘是同事。执笔本书的“实现篇”。

个人网站:http://www.narihiro.info/

相川光
游戏开发者。京都大学学习期间开始研究GC。热爱GC但讨厌打扫,除了GC之外还喜欢咖喱。执笔本书的“算法篇”。

访谈内容:

点击查看日文版

<p style="color: green;">《垃圾回收的算法与实现》深受中国读者的喜爱,图灵代表读者向两位作者的辛苦付出表示衷心的感谢!我们都知道写书不仅耗时费力,在出版后还容易遭受同行们的指责。这一点在技术书里尤为显著,两位是出于怎样的考虑,想要完成这部著作的呢?

中村: 想当年我学习GC那会儿,关于GC公开的信息并不太多,学起来真是相当费劲。因此,我写这本书是为了那些像当年的我一样“想要学习GC!”的读者,为了让他们能够更轻松地学习GC。

写起来真是不容易啊……多亏了合著者、审校和编辑的大力帮助,我才能完成这本作品。现在回眼望去,大部分都是靠着初生牛犊不怕虎的冲劲儿……(笑)

相川: 本书面向的读者是那些对编程有一定了解的人群。为了方便阅读,我尽可能地缩减了对编程基础知识的介绍,尽可能地对各个算法进行了深入的剖析。此外,为了让读者体会到垃圾回收的有趣之处,我也下了一番功夫。

中国方面已经翻译了理查德·琼斯老师的著作《垃圾回收算法手册:自动内存管理的艺术》,想必也有不少人已经掌握了一些GC相关的知识。本书中还介绍了一些在该书出版时尚未问世的算法,希望大家能从这些不同的观点中获得乐趣。

<p style="color: green;">能否向读者简要介绍下GC在程序中的作用?

中村: GC是一种能自动释放并回收程序中产生的那些看不见的垃圾(不要的内存空间)的机制。

相川: 一句话概括的话,GC就是“自动内存管理系统”。它是一个能把不再需要的内存空间自动释放和回收的机制。借助GC,程序员可以不用担心忘记释放或重复释放了内存空间,可以提高编程的效率。

<p style="color: green;">**目前存在的多种GC算法大都是对标记-清除算法、引用计数法、复制法的拆分组合。根据您的认识,未来真正意义上的第四种算法应该是怎样的?

中村: 第四种算法啊……这可很难回答啊。我感觉这种算法应该非常简单,并且能够应用于现实世界。就像一下子恍然大悟——“啊!还有这种清扫方法呢!”经常做家务的人或许会比较容易有灵感吧。(笑)

相川: 三种基本算法问世已经过去了几十年,这期间完全没有新的算法出现。因此,我觉得“真正意义上的第四种算法”不会那么简单地被发明出来。

话说回来,还有一些采用不同于GC标准来进行内存管理的方法(比如基于空间的内存管理方法)。在不久的将来,如果出现一种全新的GC算法,估计也是从这类方法的灵感中衍生出来的吧。

<p style="color: green;">很多高级编程语言内部就搭载有GC。这对GC技术研究开发者而言是怎样的机遇,又有哪些挑战?

相川: 还没怎么普及的时候,人们对GC的要求非常有限,无非是“高速化”“节约内存”,等等。近年来,搭载GC的语言被用于多种用途和各种环境,人们对GC的要求也必然变得多样。像“减少耗电量”“缩减应用程序的中断时间”等,出现了以往从未有过的高要求。为了满足这些要求,GC应该还有很大的研究空间。

中村: GC领域是一块非常复杂且具有专业性的领域,不过世界上把GC作为专业来研究的技术人员却不多。

比如说,如果大家能用打游击的形式,时不时写一些开源的高级编程语言的GC,时不时为GC领域作一些贡献的话,过不多久,大家也就能光靠GC来糊口了。

<p style="color: green;">内存管理和垃圾回收会成为未来编程语言发展时的考虑标准么?

相川: 我认为有可能,或者可以说,已经成为未来编程语言发展的考虑标准了。只要没有极其特殊的原因,编程语言都应该统一配备GC。

将GC导入编程语言,大体上有三种方法:第一种是使用Java和Python等已经安装了GC的语言来实现编程语言;第二种则是使用像BoehmGC这样的库;第三种就是自己来实现了。

从我个人的观点看,希望大家还是能够自己来挑战一次GC的实现。

中村: 对的。有这个可能,确实,内存管理和GC已经在逐渐成为未来编程语言发展时的考虑标准了。而且我认为,硬件和OS方面还将会添加一些支持,好让人们更容易编写GC。

<p style="color: green;">下面的问题来自读者实践过程中遇到的问题。

<p style="color: green;">①进程级的垃圾回收实现问题 (erlang这门语言使用进程级的垃圾回收机制,效率非常高。erlang有一个衍生语言叫elixir,elixir的语法很像ruby,它也使用erlang的垃圾回收机制(基于beam)。您和ruby的作者是同事,对ruby应该很熟悉,能有机会介绍elixir语言的垃圾回收机制吗?)

中村: Erlang的GC看来相当有意思。据说Erlang在轻量级进程间不存在共享对象,所以可以分进程进行GC。而且对象都是immutable的,因此程序绝对不可能引用对象生成后的新建对象。

从语言规范角度而言,程序只能引用曾经存在过的对象。Erlang就是利用这种特殊性质来高效实现GC复制算法的。

详细情况我也不太清楚,这个问题就请各位读者来研究了。

<p style="color: green;">②.垃圾回收算法对移动设备性能的影响问题 (有些ios app使用javascript相关的技术,v8是底层引擎使用垃圾回收算法释放资源,但有些手机内存很少(比如1G运存的iphone),垃圾回收的频率会很高。请问这种情况下垃圾回收算法会影响移动应用体验吗?如果想优化体验,应该如何设置垃圾回收算法的参数?)

中村: 我认为这取决于应用程序的性质。

如果是高实时性的应用程序(如游戏等),就需要考虑GC的问题。不过,像是Twitter和Facebook这种实时性低的应用程序,就不用太在意了。

想优化体验的话,还请了解各种GC的用法,赋予合适的参数。大家可以采用很多方法,例如缩短GC的时间间隔,或是缩小堆的大小……如果情况还不能得到改善,或许就需要考虑GC的问题,在应用程序这边修改一下代码了。

不同情况有不同的解决办法,所以不能一概而论,不能一口咬定“就这么解决!”这正是GC的难点所在。

相川: 在分代GC中有很多参数需要调整,例如分代的数量、用于晋升的阈值等。这就需要具体情况具体分析,按照不同程序的特性来相应地调整参数,不过说实话,我这方面的经验不是很多。关于这方面的知识,建议读者参照下面的链接。https://docs.oracle.com/cd/E1...(日文)

<p style="color: green;">③.在数据处理领域,如若数据量很大,特别是T级别的,应该如何选择GC策略,保证系统稳定、减少GC对程序的影响?

相川: 这也需要根据程序的特性来谨慎地选择。

我个人认为,对于那些巨大的内存空间来说,GC复制算法会比较有用(因为GC复制算法相对其他算法而言缺点要少一些)。在某些情况下,如果采用了GC复制算法但“垃圾还是较多”,可能就需要采用其他算法了。

总而言之,选择的策略很大程度上是受程序动作左右的。

中村: 这个问题的答案也取决于实际数据的类型以及想要达成的目的。

如果是注重实时性的操作,就需要采用在内部运行GC的策略(例如并行GC)。要是像Web应用那样,不在乎出现一些停顿的话,也可以采用Stop the world的算法。如果要处理的数据是可以长期存活的数据,那么即使使用分代GC,减少对处理数据的GC试运行次数,也会有效果的。

<p style="color: green;">④.怎么看待HotSpot的GC?它与DalvikVM、Rubinius的差异在哪里?有无优劣之分?

中村: 我认为HotSpot的GC很棒。我对此深感佩服,居然能灵活运用这么复杂的东西……

GC的算法各有各的优点和缺点。因此,很难判断其优劣之分……

HotSpot配备了大量的GC算法,用户可以从中随意选择。而且HotSpot也为大家准备了丰富的调优选项。就用户能够根据用例来进行选择这一点而言,我认为HotSpot的GC比其他的语言处理程序更出类拔萃。相反地,用户也会因为选项太多而找不着北……这边可谓是相当复杂呢。

也有人在研究用机器学习来决定调优参数和GC算法,不过要实际应用起来似乎并不简单。

相川: HotSpotVM最先采用了Mostly-Concurrent GC 和G1GC这些最新的算法。考虑到开发成本中还必须包括解释器和虚拟机主体,不得不说这非常值得赞叹。

话说回来,不能单纯断定它就比其他编程环境优秀。因为GC的性能很大程度上受应用程序的动作左右。因此,如果大家可以根据应用程序的特性来选择GC算法、进行参数的调整的话,说不定就能将GC的潜能发挥到极限。

HotSpotVM有很多GC算法可供选择,可以说,比起其他编程环境,HotSpotVM更容易将GC的潜能发挥得淋漓尽致。

<p style="color: green;">中村先生为Ruby 2.0新增了Non-recursive Marking 和Bitmap Marking。能否向中国的读者介绍下Non-recursive Marking 和Bitmap Marking的原理? 目前为Ruby在GC方面的发展在做着哪些努力?

在GC处理过程中会出现函数递归的现象,Non-recursive Marking就是用来防止这种情况的。我自己设计了栈结构,实现了把对象分配到栈上进行处理。

Bitmap Marking有点复杂。Ruby采用的是标记清除GC。这个GC一开始会遍历所有存活的对象,进行标记。
标记操作则会设置对象的header field中的FL_MARK标志。然后GC会再一次遍历所有的对象,清除所有已经死亡的对象的标记。问题就在于,这里破坏了CoW的语义,要标记的所有页面都Dirty了。

而Bitmap Marking只会把对象的FL_MARK标志单独拿出来,作为位图存放在一部分空间里。这样既能充分利用CoW的机制,又能优化某些程序(例如在Linux中使用了fork())中内存的用量。

现在我已经不再研究Ruby的GC,归隐山林了……

<p style="color: green;">请两位老师给有志于加入GC技术开发的后辈们一些规划、建议?

中村: GC是一个很难找到答案,却又趣味横生、充满挑战的领域。我认为理论部分很重要,但更重要的是试着亲身去研究实现的那些让人搞不清楚的地方。建议大家可以先由浅入深,之后自己试着实际操作!

相川: GC是一个非常有趣又深奥的主题。大家如果读了这本书,对这点就应该深有体会。

如果大家能读一些GC相关的论文,实现GC,跟其他的技术人士讨论GC,进一步拓展本书中体验到的趣味性和奥秘之处,我会感到无上的荣幸。


——更多访谈


更多精彩,加入图灵访谈微信!