游戏开发论坛

 找回密码
 立即注册
搜索
查看: 1396|回复: 0

请教各位大大关于动态内存管理的问题……

[复制链接]

149

主题

4981

帖子

5033

积分

论坛元老

Rank: 8Rank: 8

积分
5033
QQ
发表于 2008-1-31 01:09:00 | 显示全部楼层 |阅读模式
现在网上google到的文章里一般都是给gc说好话的,gc的问题则很少看到有人说。对于动态内存管理,之前一直是直接new/delete,最近一段时间思考了一下,觉得本来大多数时候应该充分利用?C来进行管理,其次使用内存池,再然后使用基于引用计数的智能指针,最后才使用gc。我在网上看到的一些文章的态度,大有gc一统天下的味道,而我在qq群里跟别人讨论时,也有人跟我持类似的看法:gc只是最后的手段,只是防止内存泄漏的底线手段。
在网上找到一篇文章《The Measured Cost of Conservative Garbage Collection》,根据里面的结论,gc在CPU消耗方面没有多少劣势(虽然也没有多少优势),但gc在内存换页和cache miss方面的问题比较严重,并且也会占用比手工管理或allocator更多的内存。如果真是这样,那么gc在应用于比较大的系统时,换页和cache miss可能会有损时间性能。只是这篇文章是1993年的,所以想问问现在的gc在局部性以及内存占用方面做得怎么样了。
我还注意到,gc一般都有比较大的不确定性(如果引用计数不算gc的话),并且网上有人认为RAII比较难以和gc相结合,一方面回收的时机可能会滞后而浪费资源,另一方面gc 在回收时不一定保证会调用析构函数,据说因为析构函数可能会使gc变得非常复杂。我觉得如果不能把非内存资源绑定到内存管理机制上,那么非内存资源仍然会面对手工管理动态内存时的过早释放或过晚释放问题,这样gc几乎就成了鸡肋。不知道大家怎么看这个问题。另外,我猜测局部性差的问题也是由不确定性引起的,因为gc倾向于延迟对内存的回收,因此申请内存时有更大的概率使空间占用变得分散。
最后,关于gc引起的停顿问题,我看到的解决办法是使用增量式gc。但是,如果gc频率低了,那么单次gc的工作量会倾向于比较大;如果gc频率高了,线程切换以及锁的开销又会影响性能。因此我怀疑增量式gc到底能不能在高负荷环境下用于对延迟比较敏感的程序,比如MMO服务器端。
当然以上都只是猜测,网上搜gc搜到的都是大把的赞誉之辞,所以特地来这里打听一下gc的缺陷和不适用的情况。;)

另外就是关于引用计数,由于它的确定性比gc高并且比较容易和RAII结合,所以我比较倾向于用引用计数。但是自然就要面对循环引用的问题。一种做法是用弱引用,但这样其实是把问题抛回给使用者,所以我尽量不这么做。后来我查到python里有一个循环引用探测机制,只是还不知道其具体的思想和方法,哪位大大知道的话可否简单讲解一下。^_^
关于循环引用,我思考之后是这么看的:首先假设对象全都是在特定的内存池上分配的,并且全部使用封装好的智能指针来访问。
对于一个对象,如果指向它的所有引用都在?C上,那么它一定不会牵扯到循环引用的问题,因为?C能保证?C上的引用(也就是智能指针)迟早都会被删除,这样这个对象的引用计数一定能够降到0。
对于一个对象,如果它会牵涉到循环引用而发生泄漏,那么一定存在至少一个指向它的智能指针,且该智能指针自身也在堆上(即内存池里)。所以循环引用的问题,是因为引用计数本身是以?C这种自动机制为基础的,堆上的智能指针没有了?C的支持就无法完成自动管理的任务。
所以,我在想,如果把引用计数分成两个计数器,一个记录直接外部引用的数目,另一个记录间接外部引用的数目。
直接外部引用指的是在?C上的、直接指向该对象的引用。间接外部引用,这些引用也是直接指向该对象的,但是它们都不在?C上,而是在堆上(因此也需要其他智能指针来维持其生存),并且在整个系统中,存在某个?C上的引用能够间接的、(并最终)通过该引用而得到该对象。直接外部引用可能会转变为间接外部引用,但反过来不会。
打破循环引用往往只需要删除某一个对象,就能引起链式反应。但是具体如何使用上面这种2个计数器的机制来打破循环引用,我还没考虑好,一时也想不出新的东西,所以来问下各位大大,有些什么看法~
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2025-12-19 23:40

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表