启网、虚拟主机、域名注册、服务器合租
精致合租、5人、10人、15人服务器合租、freebsd合租
当前位置:站长中国 > .NET基础 > .NET垃圾收集器的过去、现在和未来(二)

.NET垃圾收集器的过去、现在和未来(二)

2009 - 04 - 14  作者:  来源:  浏览:554  评论: 发布评论 问高手
推荐:启网 - 专业的主机、服务器合租提供商 17hz.net - 5年服务器合租精品服务
    

  Charles:想问个问题,你为什么做垃圾收集器?这个工作哪点让你觉得激动人心?你做垃圾收集器的历史是怎样的?


  Patrick:对我来说,我一直都在做运行库。很早以前我做LISP,在Schlumberger工作。他们用LISP建立一些很大的系统。我帮助他们从内部LISP工作站迁移到Deck工作站上,后者在当时运行标准LISP。做垃圾收集器的历史来源于我在LISP上的工作经历。然后,我在Austin,为德州仪器的Explorer工作,这在当时是一个受欢迎的LISP工作站。德州仪器的工作涉及运行库的各个方面,各种库、解释器、垃圾收集器,等等。然后我在Lucid工作,我们有一个供Sun工作站C++开发使用的IDE。为了管理复杂的对象交互网络,我们有一个内存中数据库,专门记录程序中各个元素的关系。比如,一个函数调用了其他五个函数,我们把这记录下来,这样我们就能根据少数函数的变化进行增量分析。如果你改变了一个函数,那依赖于这个函数的东西就必须重新编译,我们能够跟踪这种情况。如果你向一个结构体中添加了一个成员,所有使用这个成员,所有知道这个成员长度,所有能够接触到这个成员的东西都必须重新编译,我们也跟踪这种情况。本质上这就是个跟踪对象的大网络。事实上,我们当时没做一个垃圾收集器带来了大问题,搞得自己很头疼。有很多情况下我们拥有一个对象,删除了它,但是不清楚影响如何,非常头疼。在微软,我开始时做VB运行时。VB运行时不进行收集,但是自动管理。它的自动管理靠的是自动插入AddRef和Release。这套机制工作得不错,唯一的问题是AddRef和Release不可扩展。因为Release必须是被锁定的操作——我们要确保即使有两个线程同时操作,引用计数也是正确的。这样一来,AddRef和Release方式的自动内存管理就开销巨大。我做过测量,大家看见了都说开销不小,如果在多线程的环境下工作,这样的开销很要命,因为我们在多线程下要做“InterLockedIncrement”和“InterLockedDecrement”,而不是普通的增加和减少引用计数。所以,当开始为VBScript和Java写运行时的时候,我们知道必须要做垃圾收集器了。对我自己而言,我非常喜欢这个工作,这可以使你的代码运转如飞,某种意义上垃圾收集器比程序优化更具备杠杆作用。如果你有一个好的优化器,将C++程序优化提高了5%的性能,你会说,“哇,太棒了,你知道吗,程序快了5%!”垃圾收集器能使程序快30%,所以杠杆作用非常明显。当我开始这项工作时,一个挑战是服务器没有好的垃圾收集器。那个时候,垃圾收集器扩展性不好。当时的挑战是做出一个既可以透明扩展,又可以自动适应不同负载的垃圾收集器。对我来说,这项工作已经完成了。我们在做许多工作,举个例子,Channel 9上有个问题说……


  Charles:我们来看看这个问题,谁问的?


  Patrick:有个问题问到延时。有个Channel 9的网友提到,垃圾收集器是影响托管代码用于多媒体的原因之一。事实确实如此,垃圾收集器会造成内部暂停执行。说起来如果程序内部没有工作,没有执行用户的代码,那就是在进行垃圾收集。正如我前面说的,原因主要是堆栈,我们必须停止堆栈。我们内部使用一种“并发模式”。并发模式会在某些点上暂停程序,当然,暂停时间很短。然而,在许多情况下,我们会出问题,因此,程序不是暂停很短的时间,而是暂停较长的时间。这也是垃圾收集器目前在解决的问题之一。未来我们会引入一种新的并发收集方式,这是目前在做的很前沿的工作。最终,对于表现良好的程序来说,我们会将暂停时间控制在几个毫秒。目前,找到何种要素能够代表“表现良好的程序”也是一个挑战。我可以写一个只创建新对象而不使用它们的程序,因此,对象一出生就消亡了,这样的程序的暂停时间远远低于毫秒级别。问题在于,一旦开始使用这些对象,一段时间后,它们就变得难以收集,因为这些对象和别的仍应该生存的对象搅和在一起,你必须把它们区分开。最终的区分手段就是在并发模式下来一次完全的垃圾收集,然而这又导致应用程序关键工作较长的暂停。在这方面业界有许多研究工作,我们在自己的方向上进行得也不错,未来数个版本就可以体现出来。




推荐教程