关于 manual gc 的代码分析
今天发现 darkdestiny 朋友去年写了一个系列的 manual gc 的源码分析 :D
嗯,那段代码写的比较乱,居然真有人读完了,我真是佩服的紧啊。:D
这是第一篇,在那里还有 A-K,有兴趣的朋友可以自己去看。
里面提到 cache_flush
算是这个库最糟糕的一段代码了 ,好吧,我检讨,这段写的是很够戗。
代码写的乱,是我迟迟不敢把很多东西开源的主要原因 :D 。
其实一开始设计的时候,何尝不想写清楚点呢?在我自己的 svn server 上查看这个东西的修改历史,曾经也出过好几个 bug 。所以说,优化是万恶之源啊,可我们又不得不面对现实。
写的这么复杂还是因为性能缘故,希望把内存扫描次数,数据比较、内存移动、内存分配等的次数减到最少,或许以后重写一次会好一点吧。
顺便回答文章最后的一个问题:
Q: 这样这些节点不会在下一次gc_collect
的时候被回收。因为弱表的children还引用着他们,维护着依赖关系,即使分配的内存已经回收了。只有用 gc_weak_next
遍历了弱表之后,这些废弃的管理节点才会从children中被删除,最终在gc_collect的时候被回收。
为啥非要主动遍历弱表才能这样呢。。。。
A: 呵呵,因为 id 得保留,不然新分配的内存块分配出来的 id 可能和弱表里记录的重复。这样从弱表里就可能取到和当初放进去不同的内存指针了。关键是在于,回收一块内存时,无法反查到内存被哪些弱表引用着。
这个东西原理其实很简单,也就是标记-清理算法。我觉得有价值开源,是因为在我们项目的实际应用中,的确得到了许多好处。有些优化策略是值得推荐的。
比如把一切事情都推迟到非做不可的时候,这样可以快速合并删除不必要的操作。标记-清理算法本质上需要维护一张内存关系图,但是,我们不必要随时生成和拓展这张图,而可以推迟到收集发生的时候。
把内存关系图和内存块在物理上隔离,也使得系统更健壮,甚至性能更高。发生收集的时候,cpu 可以工作在很小的连续内存地址空间,减少系统内存交换。也为以后升级到并行收集做准备。
另外,如果系统整个建立在 gc 的基础上的话,finalizer 的使用其实很值得推敲。一般说来 finalizer 是用于避免太细的内存粒度,和回收非内存资源用的。如果泛泛的用于类似 C++ 的析构函数的机制,会起不到应有的效果(效果指让 gc 工作的更高效)。
Comments
Posted by: Anonymous | (14) June 8, 2012 12:38 AM
Posted by: ddd | (13) March 2, 2011 04:10 PM
Posted by: 云端孤鹜 | (12) March 25, 2009 03:19 PM
Posted by: jason | (11) March 18, 2009 10:05 AM
Posted by: jason | (10) March 18, 2009 09:55 AM
Posted by: 王者之剑 | (9) March 11, 2009 03:40 PM
Posted by: chinainvent | (8) March 10, 2009 08:27 PM
Posted by: chu | (7) March 10, 2009 11:13 AM
Posted by: jiao | (6) March 9, 2009 09:38 PM
Posted by: 云端孤鹜 | (5) March 9, 2009 08:54 PM
Posted by: madlax | (4) March 9, 2009 07:59 PM
Posted by: 程序狂 | (3) March 9, 2009 05:22 PM
Posted by: chu | (2) March 9, 2009 05:19 PM
Posted by: 程序狂 | (1) March 9, 2009 05:17 PM