负暄琐话

我的email: rot47('649@ 6(hF+`hd"w=92vhG{>}G3"@l M >:>6?4@56 \F')

囧囧ID:g9yuayon
[修改头像]
785955次访问,排名36好友9人,关注者11
g9yuayon的文章
原创 239 篇
翻译 4 篇
转载 48 篇
评论 794 篇
g9的公告
最近评论
xingranliuyun:囧囧囧rz。这难道是给脑残大学脑抽系汗语颜文学专业同学们出的毕业大补考的考试题?
GlacJAY:呃,那个讨论看不到了。被河蟹了?
Googol:这些更多是民众发泄的途经吧,作为对政府部门不作为的嘲讽。
andrewleung:说得好,支持!
alextooter:ff可是用的完全的自己内存管理。。

最近ff3非常好,值得试试看。
订阅我的博客
XML聚合  FeedSky
订阅到鲜果
订阅到Google
订阅到抓虾
订阅到BlogLines
订阅到Yahoo
订阅到GouGou
订阅到飞鸽
订阅到Rojo
订阅到newsgator
订阅到netvibes
文章分类
收藏
    相册
    旅游
    计算机科学
    Lambda the Ultimate
    软件开发
    Reddit编程专栏(RSS)
    正在读的书
    存档

    原创 关于C++ 0x 里垃圾收集器的讲座

    新一篇: Wired上关于Jim Gray的文章

    好像最近C++标准地下工会在公司附近开会,所以我们上班时偶尔可以看到工会成员矫健的身影。我们也近水楼台,得以听到关于C++0x进展的一些科普报告。上次Bjarne Stroustrup做了关于泛型编程的讲座后,Symantec实验室的Michael Spertus也做了一个关于C++ 0x里垃圾收集的讲座。Michael Spertus当年写出了IBM PC上最早的C编译器,也是C++ 0x里垃圾收集器的主要倡议人。
     
    Michael从什么是GC开始讲起。三言两语后,谈到在C++ 0x里加入GC的动机。一是许多数据结构,对象,或者资源的生命期难以事先确定、静态管理。我们需要某种形式的动态管理技术。很多老大以为C++高手的标志之一是不需要GC。如果这样想,Unreal的Tim Sweeney就笑了。Unreal引擎里就大量使用GC。如果一个系统需要管理大量对象,要求高吞吐量,但可以容忍偶尔的系统延迟的话,GC是颇为不错的工具。所以3D/建模,2D图像处理等计算都可以用到GC。第二个理由非常有煽动力:帮助C++程序清除内存泄露。我们不必在C++里排斥人肉内存管理。问题是,人肉内存管理难以尽善尽美。大型系统里内存泄露几乎不可避免。每次泄露也不多,10来KB到几个MB。但积累起来,也就造成诸多问题。因为每次泄露量不大,也不像Java等基于GC的语言,“泄露”随时都在发生。所以可以通过定期执行GC来清除这些泄露,也不用消耗过多资源。Michael后来举了一个颇有说服力的例子:某电信公司的交换机,100多万行程序,有持续的内存泄露。每小时必须重启一次。使用GC后,内存泄露消失,交换机不用再定时重启。重启时系统堆上有大概200个线程,500MB内存。这样算来,每线程每小时泄露2.5M。每线程每分钟不过42KB。而每分钟收集42KB内存对系统根本不会有什么影响。最后实测下来,收集500MB不过需要两秒种。分摊到一个小时内,完全可以忽略不计。这样的GC应该叫LC—Litter Collector。还有一个例子是Michael向Mozilla浏览器里注入GC。每次用户操作使得GC回收大概10KB的内存,实在是小菜一碟。
     
    Michael接着谈到C++ GC的发展。C++ GC已经成熟,可以标准化了。系统研究的老大们已经做了20年的研究。GC也用到了形形色色的C++系统里。标准化的关键是C++的GC是可选项:GC可以被关掉,而且程序员能够在代码里随时决定用GC还是人肉内存管理。这样才能满足某些系统实时回收资源的要求。而且已有的标准库就不需要重新编译。
     
    Michael比较了shared-ptr和GC。GC的主要缺陷是不能即时回收内存,而强项除了方便程序员外,就是性能了。GC的性能(尤其是分摊后的性能)在多方面的基准测试里超过自动指针管理已经不是新闻。Michael举了Boost线程安全基准测试的数据。GC比用share-ptr的测试程序快10倍以上。比Java的hotspot程序或者Gcj编译出的程序快5倍以上。甚至用人肉内存管理的C程序也比GC慢,不过比Boost的程序员快3倍左右。
     
    既然GC在C++里用了很多年了,干嘛还要标准化呢?主要有三条原因。一是内置的GC才能读取C++的类型系统。高质量的GC需要知道数据的类型信息。没有类型信息,GC变得非常保守,需要经常扫描大片内存来决定是否能回收某个对象。这样让GC变得很慢。第二个原因是我们需要防止编译优化对GC造成破坏。如果不标准化,标准的C++编译器不可能知道第三方的GC需要什么样的优化。第三是为了允许不同的厂家能共享GC管理的对象。不然微软在某个控件里用了GC,怎么能保证同样的控件到了Borland的系统里也正常回收内存呢?
     
    目前的C++ 0x的提议走的是稳健路线。任何功能都要经过实际应用的检验。GC用于特殊场合(比如前面的LC)。通过句法糖的方法实现,也就是说没有新的关键词。API的数目要尽可能小。当然了,C++的类型系统不如Java那么强,所以GC也相应复杂一些。标准提案里包涵了好几种GC类型:
    • gc_required: 所有资源都要通过GC收集。由gc_required控制的区域内所有指针都是经过标注的gc指针。
    • gc_forbidden: 不允许GC。必须人肉回收内存。由gc_forbidden控制的代码区域里只有原始指针。
    • gc_safe:缺省情况。忽略人肉管理的内存,但处理没有被手工回收的部分。
    • gc_strict: GC处理的代码段里整型变量不包含指针(比如不能在DWORD里放指针)。
    • gc_relax: GC处理的代码段里整型变量可以包含指针。这种情况下GC往往需要扫描大量内存来确保安全回收内存。
    • gc_cast: 把一种类型的GC转换成另外一种类型。
     
    下面是个例子:
    class A {
                A *next;
                B b; // 这里不能用gc_strict, 因为我们不知道B里的数据信息。
                gc_stric int data[10000]; // 我们肯定data数组里没有指针
    }
     
    同时C++标准库里还提供两个函数:bool std::is_garbage_collected(),和class std::gc_lock()。一个用来检查某块内存是否被GC回收,另外一块用来设定所谓的GC临界区。临界区内的内存不能被回收,这样可以防止GC不合时宜地启动。
     
    呵呵,够复杂吧?引入这么多操作的原因之一是要和老的C++系统互动。比如说下面一些情况:
    • 两个DLL,一个用了全局GC,另外一个没有怎么办?如果每个DLL都链接到自己的C类库怎么办?
    • 如果一个共享库希望在内部使用GC,但不影响堆的其它部分怎么办?
    • 如果我们在C++程序内调用libjvm怎么办?libjvm装载后,C++程序可以读取到载入的JVM里的堆,未必我们需要对已经有Java GC控制的内存再做垃圾处理?
     
    针对不同的情况,我们得祭出不同的GC。嘿嘿,C++程序员们,准备好你们的钱包哈。如果2009年后C++ 0x开始流行,要买的书就多了。比如Effective C++ GC, Master C++ GC, C++ GC with Legacy Applications,  Modern C++ Design with GC, Expert C++ with GC, Expert C++ without GC。这个世道,不容易啊。
     
     
    那finalization嗫?没有了finalization的GC还叫GC么?C++的大仙们当然不会漏掉这么重要的环节。只不过因为finalization本身就很复杂了(比如说回收内存时应该怎样调用回收对象的析构函数?如果回收时立刻调用,会造成线程不安全),所以有另外的提案讨论乐。
     
     

    发表于 @ 2007年07月23日 11:56:00|评论(loading...)|编辑

    旧一篇: 跳棋被搞定了

    评论

    #cnzhangzhen 发表于2007-07-22 23:41:48  IP: 155.56.68.*
    乖乖隆地动...
    这个世界太疯狂了, GC也要登上C++殿堂了
    #Googol 发表于2007-07-23 01:15:37  IP: 58.247.121.*
    为了照顾已有的系统,搞的还真是复杂阿……

    老大最近对c++兴趣这么大?
    2007-07-24 22:15:04作者回复
    纯好奇,去听下讲座而已。:=)
    #drdirac 发表于2007-07-23 04:10:43  IP: 125.126.175.*
    早该加入gc了,到现在已经有点晚,还弄得这么复杂
    #uoyevoli 发表于2007-07-23 06:50:06  IP: 221.201.9.*
    不容易啊,终于提前看到dc相关的东西了……
    等xxxx with GC出版的时候,你也为我们讲得差不多了……
    #jq0123 发表于2007-07-23 20:26:53  IP: 124.77.249.*
    C++的GC很复杂,但是最终是为了让编程变得简单。
    #bright2k 发表于2007-08-29 04:07:54  IP: 219.141.227.*
    有好用的c的GC没?
    #Jedimaster 发表于2007-11-10 21:01:08  IP: 218.2.198.*
    最近开始忙GC了,我就弄不清楚mental ray和RenderMan是如何在20年前用C做到的
    #alittlewolf 发表于2008-01-30 04:46:04  IP: 210.22.177.*
    人肉内存管理的C程序也比GC慢
    --------------
    这种话大家也信?
    #mathe 发表于2008-02-01 01:24:28  IP: 202.101.8.*
    人肉内存管理的C程序也比GC慢
    --------------
    这种话大家也信?
    ------------------------------------------------
    某种情况可能.

    不过对于C++中采用GC,我是疑虑重重,不知道能否解答一下我的顾虑,下面链接是我的问题所在,顺便我也介绍了一下GC通常实现的原理:

    http://bbs.emath.ac.cn/viewthread.php?tid=130&extra=page%3D1&frombbs=1
    #Could 发表于2008-02-19 20:43:48  IP: 220.231.200.*
    GC已经被搁浅了,但是还有点希望,
    我最遗憾的是网络相关的库,看样子不能加入到C++0x中去了,
    倒是线程相关的库,赶鸭子上架弄了一个塞进去。
    发表评论  


    当前用户设置只有注册用户才能发表评论。如果你没有登录,请点击登录
    Csdn Blog version 3.1a
    Copyright © g9