您已经编写了一个幼稚的微基准测试。在JVM上进行微基准测试是一项非常棘手的事情,要列举所有的陷阱甚至不容易,但是这里有一些经典的方法:
- 您必须预热代码;
- 您必须控制垃圾收集暂停;
System.currentTimeMillis
是不精确的,但您似乎甚至都不知道这种方法(您的方法new Date().getTime()
是等效的,但速度较慢)。
如果要正确执行此操作,请查看Oracle的
jmh工具或Google的Caliper。
我的测试结果
由于我很想亲自查看这些数字,因此这里是的输出
jmh。一,测试代码:
public class Benchmark1{ static Integer[] ints = new Integer[0]; static { final List<Integer> list = new ArrayList(asList(1,2,3,4,5,6,7,8,9,10)); for (int i = 0; i < 5; i++) list.addAll(list); ints = list.toArray(ints); } static List<Integer> intList = Arrays.asList(ints); static Vector<Integer> vec = new Vector<Integer>(intList); static List<Integer> list = new ArrayList<Integer>(intList); @GenerateMicroBenchmark public Vector<Integer> testVectorAdd() { final Vector<Integer> v = new Vector<Integer>(); for (Integer i : ints) v.add(i); return v; } @GenerateMicroBenchmark public long testVectorTraverse() { long sum = (long)Math.random()*10; for (int i = 0; i < vec.size(); i++) sum += vec.get(i); return sum; } @GenerateMicroBenchmark public List<Integer> testArrayListAdd() { final List<Integer> l = new ArrayList<Integer>(); for (Integer i : ints) l.add(i); return l; } @GenerateMicroBenchmark public long testArrayListTraverse() { long sum = (long)Math.random()*10; for (int i = 0; i < list.size(); i++) sum += list.get(i); return sum; }}结果:
testArrayListAdd 234.896 ops/msectestVectorAdd 274.886 ops/msectestArrayListTraverse 1718.711 ops/msectestVectorTraverse 34.843 ops/msec
请注意以下几点:
- 在
...add
方法中,我正在创建一个新的本地集合。JIT编译器利用这一事实, 消除 了对Vector
方法的锁定,因此性能几乎相等。 ...traverse
我从全局集合中读取的方法中;不能消除锁,这是真正的性能损失所在Vector
。
这样做的主要收获应该是: JVM上的性能模型非常复杂,有时甚至是不稳定的
。从微观基准推断,即使在采取所有适当措施的情况下,也可能导致对生产系统性能的危险错误预测。



