首先你要明白回收语言性能不手动系差,甚至在各种需要作大量指针的程序更好。
这是因为两点。
<>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++快?>
这是计算机领域的一个巨大归因谬误。我们先来看看这段代码: