为什么是代码的第二片更快?

Map<Integer, Double> map = new HashMap<Integer, Double>();
for (int i = 0; i < 50000; i++) {
    for (double j = 0.0; j < 10000; j++) {
        map.put(i, j);
    }
}

Map<Integer, Double> map=new HashMap<Integer, Double>();
for (int i = 0; i < 50000; i++) {
    for (double j = 0.0; j < 10000; j++) {            
        map.put(new Integer(i), new Double(j));
    }
}
有帮助吗?

解决方案

自动装箱使用Integer.valueOf,其在内部缓存Integer对象为小整数(默认-128到127,但是最大值可以用“java.lang.Integer.IntegerCache.high”属性被配置 - 见的源代码Integer.valueOf),所以它是直接调用new Integer不同。由于Integer.valueOf做为整数值的大小进行快速检查调用new Integer之前,这是一个有点快调用new Integer直接(尽管它使用的,如果你有很多小整数的更多的内存)。分配在Java是非常快的,并且这样做GC的时间正比于活短命的对象(即不成正比垃圾的量)的数量,所以GC也非常快。

但根据JVM版本和优化启用,有标量替换优化,可分配短命的对象(在你的例子,优化无法做到时产生更大的性能差异,因为要存储的对象中的映射,但在许多其它情况下这是有用的)。

在最近的JVM版本有标量替换优化(除了在1.6.0_18其中逃逸分析是暂时停用),这意味着那短命的对象分配可以被优化掉。当JVM标更换为新的,有人提出基准那里有类似于你的代码。其结果是,它使用的原语的代码是最快的,具有明确new Integer()调用的代码几乎一样快的一个使用原语,并用自动装箱是慢得多的代码。这是因为自动装箱用途Integer.valueOf和至少当时标量替换优化并没有采取这种特殊情况考虑进去。我不知道是否优化从那以后得到了改善。

其他提示

自动装箱将使用Integer.valueOfDouble.valueOf。有一个在调用这些方法(虽然它最终会得到内联)的一些开销。此外Integer.valueOf做了一些检查低值使用集中的情况下,这是不是经常在你的代码的胜利(虽然它可能减少堆大小略)。汇集实例可以是一个双赢其中它们降低堆大小,GC倍,甚至可能提高平等测试性能..

不过,在一般情况下,这是一个microoptimisation,你应该在一般情况下,忽略。

由于微基准的结果是不可靠?

另外,自动装箱使用Integer.valueOf()和Double.valueOf(),而不是构造完成。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top