测量创建和销毁简单对象的时间

时间:2010-04-03 14:06:43

标签: java time object measurement finalizer

从Effective Java 2nd Edition第7项:避免终结器

“哦,还有一件事:使用终结器会严重影响性能。在我的机器上,创建和销毁一个简单对象的时间约为5.6 ns。添加终结器会将时间增加到2,400 ns。换句话说,使用终结器创建和销毁对象的速度要快430倍。“

如何衡量创建和销毁对象的时间? 你做的只是:

long start = System.nanoTime();
SimpleObject simpleObj = new SimpleObject();
simpleObj.finalize();
long end = System.nanoTime();
long time = end - start;

4 个答案:

答案 0 :(得分:2)

仅测量执行finalize方法的时间。最终确定的绝大部分费用将由GC必须执行的特殊处理。

答案 1 :(得分:1)

正如Tom Hawtin上面所说的那样,最好的方法是检查创建和销毁几十万个循环的时间,并除以循环次数,而不是徒劳地试图对此进行微观标记。

在许多情况下,这种方法是最好的,在这种情况下,您编写的代码不是唯一涉及的代码 - 您依赖于系统调用或外部资源。

我认为这就是Joshua Bloch在这种情况下所做的,但是我的副本在楼上,我感觉很懒。

答案 2 :(得分:0)

您可以请求运行时通过Runtime.gc()执行垃圾收集,但垃圾收集器不需要在那里执行它然后:

  • 您不会调用finalize()方法,而是由垃圾收集器调用
  • 您只需将simpleObj设置为null,然后调用垃圾收集即可实现更逼真的场景

答案 3 :(得分:0)

一种可能的解决方案是依赖 java.lang.ref 包,该包仅支持与垃圾收集器的有限程度的交互。

测量结果不准确,因为很难知道物体的真正结局。我相信 Joshua 必须有另一种方法来衡量时间,也许前往 JVM 本身。

PhantomReference 最接近对象生命周期结束的引用。换句话说,对象是幻影可达

public class WithoutFinalizationV1 {
    
    public static void main(String[] args) {
        ReferenceQueue<WithoutFinalizationV1> queue = new ReferenceQueue<>();
        long start = System.nanoTime();
            
        PhantomReference<WithoutFinalizationV1> rf = new PhantomReference<>(
        new WithoutFinalizationV1(), queue);
        System.gc(); //advise JVM to do GC
            
        Object x = null;
        int waitCount = -1;
        do{
            x = queue.poll();
            waitCount++;
        } while(x == null);
            //only need this time point
        System.out.println("WithoutV1 "+ waitCount + " " + (System.nanoTime() - start));
    }
}

跑了几次,世界纪录是5394860ns,远不是5.6ns。

添加后

@Override
protected void finalize() throws Throwable {
}

结果是 5632208ns。

Here 摘自我写的相关帖子。