在Java中使用弱引用的成本
有没有人研究了创build和垃圾收集Java WeakReference对象所涉及的运行时成本? multithreading应用程序是否存在性能问题(如争用)?
编辑:显然实际的答案将是JVM的依赖,但一般的意见也是受欢迎的。
编辑2:如果有人已经做了一些基准的performance,或者可以指出一些基准的结果,这将是理想的。 (抱歉,但赏金已过期…)
WeakReference对CMS垃圾回收器有负面影响。 据我所知,从我们的服务器的行为,它影响并行备注阶段时间。 在这个阶段,所有的应用程序线程都停止了,所以这是非常不可取的。 所以你需要小心WeakReferences。
我实现了一个Java垃圾收集器,所以无论我能够完成什么是可能的(弱)下界。
在我的实现中,在垃圾收集过程中访问每个弱引用时,会有less量的额外开销。
所以结果是:我不会担心,除非你使用了大量的弱引用,否则这不是一个大问题。
最重要的是,成本与存在的弱引用的数量成正比,而不是整个堆的大小。
但是,这并不是说支持弱引用的垃圾收集器将会像没有引用的那样快。 这里推测的问题是,鉴于Java支持弱引用,使用它们的增量成本是多less?
矿是一个简单的“停止世界”标记/清扫垃圾收集器。 在垃圾收集过程中,它会确定每个对象是否存在该对象,并在对象头中设置一个LIVE
位。 然后它通过并释放所有非活的对象。
要处理弱引用,只需添加以下内容:
- 设置
LIVE
位时忽略弱引用(即,它们不会导致引用对象上的LIVE
位被设置)。 - 在扫描步骤中,添加一个特殊的检查如下:如果你正在访问的对象是
LIVE
,并且是WeakReference
,那么检查它弱引用的对象,如果该对象不是LIVE
,清除引用。
这种逻辑的小变化适用于软和幻影参考。
如果你真的好奇,实现就在这里 。
使用弱引用的caching可能会显着减慢你的应用程序,如果它需要重build,例如在getters中:
public Object getSomethingExpensiveToFind() { if(cache.contains(EXPENSIVE_OBJ_KEY)) { return cache.get(EXPENSIVE_OBJ_KEY); } Object sth = obtainSomethingExpensiveToFind(); // computationally expensive cache.put(EXPENSIVE_OBJ_KEY, sth); return sth; }
想象这个场景:
1)应用程序内存不足
2)GC清除弱引用,从而清除caching
3)应用程序继续,调用getSomethingExpensiveToFind()等许多方法并重buildcaching
4)应用程序再次在内存中运行不足
5)GC清除磨损引用,清除caching
6)应用程序继续,调用getSomethingExpensiveToFind()等很多方法并重新生成caching
7)等等…
我遇到了这样的问题 – 这个应用程序经常被GC打断,它完全打败了整个caching点。
换句话说,如果pipe理不当,弱引用会减慢你的应用程序。