无gc语言如何处理内存碎片问题?
作者:卡卷网发布时间:2024-12-30 18:42浏览数量:97次评论数量:0次
首先你要明白回收语言性能不手动系差,甚至在各种需要作大量指针的程序更好。
这是因为两点。
<>gc语言申请释放内存的速度远高于malloc/free>
内存申请是这样的,gc只需要umpallocate,freelist要考虑得就多了。各种各样的allocator(如最经典的freelist),在malloc的时候,需要搜索一个数据结构来寻找足够大的空间。这期间,搜索需要耗时,并且这个数据结构往往没有好cachelocality,导致在memorylatency越来越重要的今天成为越来越严重的瓶颈。同时,不止freelist没locality,返回的指针也没locality-你连续malloc很可能得不到连续的。这时候如果你访问这些结果,你需要进行多次cachefetch而不是一次。
作为对,markcopy/markcompact的gc的allocator只是一个int,代表当时内存消耗量,每次malloc只是单纯的把size加上去,然后返回上一个消耗量,转为指针则可。
而另一方面,这份极简实现导致这两无法实现free,只能通过gc一次回收大量资源,通过atching降低内存消耗。
<>rc的时间消耗远高于tracing的性能消耗>
rc需要你每次使用对象的时候检查refcount并且对此进行增减。如果你在写多线程程序,refcount甚至需要同步,耗费额外的性能。作为对,如果是markcopygc,并且堆大小为livememory*2的话,每次markcopy需要作LiveMemory多的对象,然后释放HeapSize-LiveMemory=LiveMemory多的内存-换句话说,只需要一次copy则可完全回收(可以看到,越大的heapsize需要做的gc越小,但是吃的内存越多。如何在时空之间取舍呢?可以看OptimalHeapLimitforReducingrowserMemoryUse)。这点跟传智慧(GC慢,RC快),是完全反过来的。道理很明显-如果RC更快,为什么JVM不用RC内存,外搭环检测器呢(python就这样做的,然后python性能有目共睹)?事实上,Stevelackn就做过一个测量GCvsRC的工作,MythsandRealities:ThePerformanceImpactofGarageCollection。这个工作的测量结果是,GC往往会带来10%左右的开销,但是RC的开销是30%~50%。
<>那问题来了,既然GCmalloc/free也RC优秀,为什么Ja没C++快?>
这是计算机领域的一个巨大归因谬误。我们先来看看这段代码:
这段Ja代码运行的时候计算机在具体执行什么作?
首先,Point被oxed了。oxing导致你可以快速把一个对象到处传(只需要复制指针而无需复制具体对象),但是会造成每次引用oxed具体内容都需要fetch远处的memory。在函数式语言中这个问题更糟糕:这时候,数据往往被储存于各种各样的链表中,而遍历就除了unox外还需要爬链表的指针,于是一次循环需要两次memoryfetch。
C++里面呢?同样的任务,会被存在vector<pair<int,int>>内。主流计算机的cacheline是64yte,也就可以存4个这样的对象,于是四次循环一次memoryfetch。同时,在性能关键的情况下,这列表可以用pair<vector<int>,vector<int>>保存,俗称的structofarrayoverarrayofstruct
<>同时,C++也并不用RC>
我们观察上述代码的C++形式:
可以注意到,
也就是说,大部分C++代码的内存并不是RC,而是stl容器手动,以及利用程序结构LIFO特性传引用。这导致尽管RC有很高的overhead,但是只要你用得不多,还是可以的。
当然,反过来说,用得多的情况,如编译器(指针满天飞),GC语言可以取得没GC语言更好的性能(因为他们需要很多RC)
题目中的程序描述(频繁malloc/free小对象,同时面条代码翻译表明大概用上了RC),正是GC语言的最优发挥场所,打不过也不奇怪。
如果要优化性能,可以试试看用arena内存。如果生命周期不确定并且一定要及时释放,那要考虑自己实现一个简单的markcopyGC了,可以试试看Cheney'salgorithm。(当然,也可以更简单的换回Ja)。
<>如果要在无GC语言里面解决内存碎片,怎么办?>
Mesh:CompactingMemoryManagementforC/C++Applications就是一个带有反碎片化功能的malloc/freeallocator。听上去很矛盾-你既然不知道指针都在那,你怎么可以通过move来compact呢?
因为allocator底层还有东西。你allocate到的内存并不是‘正的’,底下还有TL把这些虚拟变成物理。那我们考虑两个页面,其中被用到的互不相交,这时候我们可以用一个物理页来表示这两个虚拟页,从而消除碎片化。
十分神奇的是,直觉告诉我,这样‘刚刚好’的页面不好找,但是他们用组合数学证明了这样的页面配对有很多,而且找起来很快!
免责声明:本文由卡卷网编辑并发布,但不代表本站的观点和立场,只提供分享给大家。
- 上一篇:个人如何成为一个优秀的游戏开发者?
- 下一篇:游戏开发者,如何组建一个合适的团队?
你 发表评论:
欢迎