大多数程序员都认为垃圾收集是一件好事,在大多数应用程序中都非常值得花费.但是,我个人的观察是,大多数对象的内存管理都是微不足道的,并且可能有10%-20%的内存管理需要考虑诸如
int myFunc() { Foo[] foo = new Foo[arbitraryNumber]; // May be too big to stack allocate. // do stuff such that the compiler can prove foo doesn't escape. // foo is obviously no longer needed, can be automatically deleted here. return someInteger; }
当然,这可能不适用于复制GC,但是为了这个帖子,我们假设我们的GC没有复制.为什么这种混合内存管理方案在主流编程语言中显然如此罕见?
因为这种情况太罕见了.几乎没有方法被孤立.它们都接受来自外部的对象或创建对象并将其传递出去.一个不访问任何字段,没有参数但不返回某些内容的方法无法执行任何操作.
相反,GCs专注于最常见的案例(90%),并试图控制那些90%(短期临时对象).这意味着在常见情况下,您需要检查的对象较少,其余的并不重要.接下来,您使用增量扫描(因此您可以在少量冲刺中运行,这只会在短时间内中断).
我曾经试图想出一个更好的GC算法并且失败了.他们使用的方法与奥术相邻.关于Java 5 GC Performance Tuning的文档应该给你一些想法.当然还有GC article in Wikipedia.
它归结为:使用GC甚至可以比传统的内存分配和释放模式更快.想想经典算法,它只是定位任何可到达的对象并将其复制到新的位置.如果你刚忘记了很多对象(比如所有已分配对象的90%),这个算法只需要检查其余的对象(10%).任何无法达到的东西,无论多么重要,都无关紧要.现在你可能会说复制很昂贵但是a)这不是真的;今天平均台式机CPU可以在不到100毫秒的时间内复制40MB而且b)复制将保护你不受碎片影响,所以它实际上是一件好事.